rbcalc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +34 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +17 -0
- data/Rakefile +1 -0
- data/lib/rbcalc.rb +57 -0
- data/lib/rbcalc/engine.rb +42 -0
- data/lib/rbcalc/version.rb +3 -0
- data/rbcalc.gemspec +26 -0
- data/spec/rbcalc_spec.rb +49 -0
- data/spec/spec_helper.rb +10 -0
- data/vendor/bcalc/bcalcdds.h +307 -0
- data/vendor/bcalc/libbcalcdds.dylib +0 -0
- data/vendor/bcalc/libbcalcdds.so +0 -0
- data/vendor/bcalc/test.c +88 -0
- data/vendor/bcalc/win32/libbcalcdds.dll +0 -0
- data/vendor/bcalc/win64/libbcalcdds.dll +0 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YWRlMjgwYzBkM2U3NTQyOTNjNWI2YWNmZTM5ODc1ZjhhMjUxZjMyMA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
Y2EyZGZhZDIxYmZkOWMzMmQ2MzZkMWM0ZDNhM2VlNWUyMGM4YjQ4ZA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YjJiYmJhYWE0YzM0YmZkNzQxOTFhYTM0ODVmN2U5MWE4YjVhNzIzOTExNTZm
|
10
|
+
YTZjMTRlODU1NjBiNWZhZWVjMjUyOTM3NGZjMjkxM2E3ZTZmODM4ZWU5YzRl
|
11
|
+
YzUxZmFmMWZmYWJiMTJmZTg4NDY0NGIxZTBhNTVjY2E3YWJjMDE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZTc3YjAzZjRkM2QzZmU3NDJkY2QxMTRiOWYyYjc3ODBiZWUzNDcwZGExYTkz
|
14
|
+
MWY2YWEwYTdiNDU0NTdiMmY0NWM5MTQwYTA2NTE4NWIyMGYyN2NiMjg0MDY0
|
15
|
+
ZWNlOWMzMGFhYzAzOWU3NjZlOGU3ZTNlZWFhZjViZTcxZGY2OTg=
|
data/.gitignore
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Achilles Charmpilas
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Rbcalc
|
2
|
+
|
3
|
+
Ruby bindings for Piotr Beling's [Bridge Calculator](http://bcalc.w8.pl/)
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rbcalc'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rbcalc
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/rbcalc.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Rbcalc
|
6
|
+
def self.os
|
7
|
+
@os ||= (
|
8
|
+
host_os = RbConfig::CONFIG['host_os']
|
9
|
+
case host_os
|
10
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
11
|
+
:windows
|
12
|
+
when /darwin|mac os/
|
13
|
+
:macosx
|
14
|
+
when /linux/
|
15
|
+
:linux
|
16
|
+
when /solaris|bsd/
|
17
|
+
:unix
|
18
|
+
else
|
19
|
+
raise Error::WebDriverError, "unknown os: #{host_os.inspect}"
|
20
|
+
end
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.home
|
25
|
+
Pathname.new(__FILE__).dirname
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.init!
|
29
|
+
vpath = self.home.join('..','vendor','bcalc')
|
30
|
+
incpath = Pathname('/usr/local/include')
|
31
|
+
libpath = Pathname('/usr/local/lib')
|
32
|
+
# prepare library for linking
|
33
|
+
case Rbcalc.os
|
34
|
+
when :macosx
|
35
|
+
unless File.exists?(libpath.join('libbcalcdds.dylib'))
|
36
|
+
FileUtils.ln_s(vpath.join('libbcalcdds.dylib'),libpath.join('libbcalcdds.dylib'))
|
37
|
+
end
|
38
|
+
unless File.exists?(incpath.join('bcalcdds.h'))
|
39
|
+
FileUtils.ln_s(vpath.join('bcalcdds.h'),incpath.join('bcalcdds.h'))
|
40
|
+
end
|
41
|
+
when :linux
|
42
|
+
unless File.exists?(libpath.join('libbcalcdds.so'))
|
43
|
+
FileUtils.ln_s(vpath.join('libbcalcdds.so'),libpath.join('libbcalcdds.so'))
|
44
|
+
end
|
45
|
+
unless File.exists?(incpath.join('bcalcdds.h'))
|
46
|
+
FileUtils.ln_s(vpath.join('bcalcdds.h'),incpath.join('bcalcdds.h'))
|
47
|
+
end
|
48
|
+
else
|
49
|
+
raise Error::WebDriverError, "Rbcalc cannot currently run on #{Rbcalc.os}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Rbcalc.init!
|
55
|
+
|
56
|
+
require "rbcalc/version"
|
57
|
+
require "rbcalc/engine"
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'inline'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
=begin rdoc
|
5
|
+
require 'rbcalc'
|
6
|
+
e = Rbcalc::Engine.new(
|
7
|
+
hands: 'S2579H38AD458QC26,S4H24569TJQKD9CJK,S36TQH7D23TKC379Q,SAKJ8HDAJ76CAT854',
|
8
|
+
played: 'e', leader: 0, trump_suit: 2
|
9
|
+
)
|
10
|
+
=end
|
11
|
+
module Rbcalc
|
12
|
+
class Engine
|
13
|
+
attr_accessor :hands, :leader, :trump_suit, :played, :tricks_made
|
14
|
+
|
15
|
+
def initialize params = {}
|
16
|
+
params.map { |k,v| self.send(:"#{k}=",v) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse!
|
20
|
+
if hands.nil? || hands.empty? || leader.nil? || trump_suit.nil?
|
21
|
+
raise ArgumentError, 'Rbcalc needs at least the hands, dealer direction and trump suit'
|
22
|
+
end
|
23
|
+
|
24
|
+
self.tricks_made = solve(hands, "#{played.to_s} e", trump_suit, leader)
|
25
|
+
end
|
26
|
+
|
27
|
+
inline do |b|
|
28
|
+
b.add_compile_flags "-l bcalcdds"
|
29
|
+
b.include '<stdio.h>'
|
30
|
+
b.include '<bcalcdds.h>'
|
31
|
+
b.c %{int solve(const char * hands, const char * played, int strain, int leader){
|
32
|
+
int res;
|
33
|
+
BCalcDDS* solver = bcalcDDS_new("LIN", hands, strain, leader);
|
34
|
+
if (solver == 0) exit(1); //out of memory error
|
35
|
+
bcalcDDS_exec(solver, played);
|
36
|
+
res = bcalcDDS_getTricksToTake(solver);
|
37
|
+
bcalcDDS_delete(solver);
|
38
|
+
return res;
|
39
|
+
}}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/rbcalc.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rbcalc/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rbcalc"
|
8
|
+
spec.version = Rbcalc::VERSION
|
9
|
+
spec.authors = ["Achilles Charmpilas"]
|
10
|
+
spec.email = ["ac@humbuckercode.co.uk"]
|
11
|
+
spec.description = %q{Ruby bindings for Piotr Beling's Bridge Calculator}
|
12
|
+
spec.summary = %q{Ruby bindings for Piotr Beling's Bridge Calculator}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_dependency "RubyInline", "~> 3.12"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
spec.add_development_dependency "fuubar"
|
26
|
+
end
|
data/spec/rbcalc_spec.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rbcalc do
|
4
|
+
it 'can detect os' do # my dev machine
|
5
|
+
Rbcalc.os.should eq(:macosx)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Rbcalc::Engine do
|
10
|
+
it 'raises error is an invalid parse is requested' do
|
11
|
+
expect { subject.parse! }.to raise_error
|
12
|
+
subject.hands = 'S2579H38AD458QC26,S4H24569TJQKD9CJK,S36TQH7D23TKC379Q,SAKJ8HDAJ76CAT854'
|
13
|
+
expect { subject.parse! }.to raise_error
|
14
|
+
subject.leader = 0
|
15
|
+
expect { subject.parse! }.to raise_error
|
16
|
+
subject.trump_suit = 2
|
17
|
+
expect { subject.parse! }.to_not raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with valid game' do
|
21
|
+
subject {
|
22
|
+
Rbcalc::Engine.new(
|
23
|
+
hands: 'S2579H38AD458QC26,S4H24569TJQKD9CJK,S36TQH7D23TKC379Q,SAKJ8HDAJ76CAT854',
|
24
|
+
leader: 0, trump_suit: 2
|
25
|
+
)
|
26
|
+
}
|
27
|
+
|
28
|
+
it 'solves a game' do
|
29
|
+
subject.parse!
|
30
|
+
t1 = subject.tricks_made
|
31
|
+
subject.tricks_made.should be_a(Integer)
|
32
|
+
|
33
|
+
# if we swap leaders, tricks should be inversed
|
34
|
+
subject.leader = 1
|
35
|
+
subject.parse!
|
36
|
+
(t1 + subject.tricks_made).should eq(13)
|
37
|
+
|
38
|
+
subject.leader = 0
|
39
|
+
subject.trump_suit = 2
|
40
|
+
subject.parse!
|
41
|
+
t1 = subject.tricks_made
|
42
|
+
subject.tricks_made.should be_a(Integer)
|
43
|
+
|
44
|
+
subject.leader = 1
|
45
|
+
subject.parse!
|
46
|
+
(t1 + subject.tricks_made).should eq(13)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,307 @@
|
|
1
|
+
#ifndef __BELING__BCALC_BRIDGE_SOLVER__
|
2
|
+
#define __BELING__BCALC_BRIDGE_SOLVER__
|
3
|
+
|
4
|
+
/** @file
|
5
|
+
* Bridge Calculator API header file.
|
6
|
+
*/
|
7
|
+
|
8
|
+
/*! \mainpage Bridge Calculator (C API)
|
9
|
+
|
10
|
+
\section about About
|
11
|
+
This is documentation for C API (and library) for Bridge Calculator engine, a fast double dummy solver.
|
12
|
+
|
13
|
+
Bridge Calculator and its C API are develop by Piotr Beling.
|
14
|
+
More information can be found on a program web-page: http://bcalc.w8.pl/
|
15
|
+
|
16
|
+
\section license License
|
17
|
+
Bridge Calculator (and its C API) is freeware for private and non-commercial use (use to develop freeware applications)
|
18
|
+
and it's distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
19
|
+
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
20
|
+
|
21
|
+
Each distributed product which use this API/library should includes readable for end-user information about this fact
|
22
|
+
and link to Bridge Calculator web-page: http://bcalc.w8.pl/
|
23
|
+
|
24
|
+
If you need license to develop commercial (payment) application, please contact with me: qwak82@gmail.com
|
25
|
+
|
26
|
+
\section example Example
|
27
|
+
@code
|
28
|
+
//create solver
|
29
|
+
BCalcDDS* solver = bcalcDDS_new("PBN", "N:.63.AKQ987.A9732 A8654.KQ5.T.QJT6 J973.J98742.3.K4 KQT2.AT.J6542.85", BCALC_NT, BCALC_PLAYER_NORTH);
|
30
|
+
if (solver != 0) exit(1); //out of memory error
|
31
|
+
//use it, print player to play, and how many tricks his line can take:
|
32
|
+
printf("%c playes, and he with partner will be able to take %d tricks.\n",
|
33
|
+
bcalc_playerSymbol(bcalcDDS_getPlayerToPlay(solver)),
|
34
|
+
bcalcDDS_getTricksToTake(solver)
|
35
|
+
);
|
36
|
+
bcalcDDS_exec(solver, "7D x x"); //play 7 of dimamonds, and two smallest diamonds
|
37
|
+
//print current situation:
|
38
|
+
printf("%c playes, and he with partner will be able to take %d tricks.\n",
|
39
|
+
bcalc_playerSymbol(bcalcDDS_getPlayerToPlay(solver)),
|
40
|
+
bcalcDDS_getTricksToTake(solver)
|
41
|
+
);
|
42
|
+
bcalcDDS_delete(solver); //and delete (free memory)
|
43
|
+
@endcode
|
44
|
+
|
45
|
+
\section names Names
|
46
|
+
All names defined by library have prefixes:
|
47
|
+
- BCALC_ - consts (defines)
|
48
|
+
- BCalc - types (for example: BCalcDDS)
|
49
|
+
- bcalc - functions and macros
|
50
|
+
- bcalcDDS - functions which operates on BCalcDDS (almost all takes BCalcDDS* as first argument)
|
51
|
+
|
52
|
+
\section changes Changes and Backward Compatibility
|
53
|
+
- ver. 14020 (5 II 2014):
|
54
|
+
- compatibility: API - yes (changes of application source are not required), ABI - yes (recompilation of application is not required),
|
55
|
+
- new function bcalcDDS_getTricksToTakeEx, this is extendend version of bcalcDDS_getTricksToTake and takes new, optional arguments: tricks_target and card,
|
56
|
+
- new function bcalcDDS_clone,
|
57
|
+
- in many places, the ASCII symbols of the suits, strains or players are accepted (as well as BCALC_* constants)
|
58
|
+
*/
|
59
|
+
|
60
|
+
#ifdef __cplusplus
|
61
|
+
extern "C" {
|
62
|
+
#endif
|
63
|
+
|
64
|
+
/**
|
65
|
+
Version of bcalc engine API.
|
66
|
+
|
67
|
+
Bridge Calculator program version (unsigned integer in form YYMMN) on which base engine.
|
68
|
+
Note that engine is released less often than program (in some program release engine is not changed).
|
69
|
+
@see @ref bcalc_runtimeVersion
|
70
|
+
*/
|
71
|
+
#define BCALC_VERSION 14020
|
72
|
+
|
73
|
+
/**
|
74
|
+
Handler to bcalc double dummy solver.
|
75
|
+
|
76
|
+
Double dummy solver represents game with history of play.
|
77
|
+
It also stores many values which was calculated for it.
|
78
|
+
|
79
|
+
Usualy you should only use pointer to this type.
|
80
|
+
*/
|
81
|
+
typedef struct BCalcDDS BCalcDDS;
|
82
|
+
|
83
|
+
#define BCALC_PLAYER_NORTH 0 ///<North player
|
84
|
+
#define BCALC_PLAYER_EAST 1 ///<East player
|
85
|
+
#define BCALC_PLAYER_SOUTH 2 ///<South player
|
86
|
+
#define BCALC_PLAYER_WEST 3 ///<West player
|
87
|
+
|
88
|
+
/**
|
89
|
+
Convert player number to player symbol.
|
90
|
+
@param player player number, one of BCALC_PLAYER_*
|
91
|
+
@return player symbol, one of 'N', 'E', 'S', 'W'
|
92
|
+
*/
|
93
|
+
#define bcalc_playerSymbol(player) ("NESW"[player])
|
94
|
+
|
95
|
+
/**
|
96
|
+
Calculate hand relative to given one.
|
97
|
+
@param hand one of BCALC_PLAYER_*
|
98
|
+
@param delta clock-wise delta, +1 to next player (in clock-wise)
|
99
|
+
@return calculated hand, one of BCALC_PLAYER_* value
|
100
|
+
*/
|
101
|
+
#define bcalc_nextHand(hand, delta) (((hand)+(delta))&3) //or (((hand)+(delta))%4)
|
102
|
+
|
103
|
+
/**
|
104
|
+
Calculate leader hand using @p declarer hand.
|
105
|
+
@param declarer
|
106
|
+
@return player on lead in deal where @p declarer is declarer
|
107
|
+
*/
|
108
|
+
#define bcalc_declarerToLeader(declarer) bcalc_nextHand(declarer, 3)
|
109
|
+
|
110
|
+
#define BCALC_SUIT_CLUBS 0 ///<Club suit number
|
111
|
+
#define BCALC_SUIT_DIAMONDS 1 ///<Diamond suit number
|
112
|
+
#define BCALC_SUIT_HEARTS 2 ///<Hearts suit number
|
113
|
+
#define BCALC_SUIT_SPADES 3 ///<Spades suit number
|
114
|
+
|
115
|
+
#define BCALC_NT 4 ///<No trump
|
116
|
+
|
117
|
+
/**
|
118
|
+
Convert @p suit number to its ASCII symbol.
|
119
|
+
@param suit suit, one of BCALC_SUIT_*
|
120
|
+
@return suit symbol, one of 'C', 'D', 'H', 'S', 'N' (for NT)
|
121
|
+
*/
|
122
|
+
#define bcalc_suitSymbol(suit) ("CDHSN"[suit])
|
123
|
+
|
124
|
+
/**
|
125
|
+
Get the version of the API used by the runtime library.
|
126
|
+
@return the version of the API used by the (typically: dynamic) runtime library
|
127
|
+
@see @ref BCALC_VERSION
|
128
|
+
*/
|
129
|
+
unsigned bcalc_runtimeVersion();
|
130
|
+
|
131
|
+
/**
|
132
|
+
Construct new solver.
|
133
|
+
|
134
|
+
Each solver has own memory and it is thread safety to operate on multiple solvers at the same time,
|
135
|
+
but it is not safety to call more than one bcalcDDS_* function for one solver at the same time.
|
136
|
+
@param format Format of @p hands, for example "NESW", "ESWN", ..., "PBN", "LIN":
|
137
|
+
- "PBN" is Portable Bridge Notation like format,
|
138
|
+
- "lin" is BBO .lin like format,
|
139
|
+
- rest show order of hands.
|
140
|
+
@param hands Players hands. Each player must have the same number of cards.
|
141
|
+
To get situation inside trick, you should create trick's beginning situation and call bcalcDDS_exec to play cards included in current trick.
|
142
|
+
@param strain one of BCALC_SUIT_* or BCALC_NT constant or ASCII symbol of strain (one of: 'c', 'C', 'd', 'D', 'h', 'H', 's', 'S', 'n', 'N')
|
143
|
+
@param leader player on lead, one of BCALC_PLAYER_* constant or player ASCII symbol (one of: 'n', 'N', 'e', 'E', 's', 'S', 'w', 'W')
|
144
|
+
@return Constructed solver or NULL in case of out of memory.
|
145
|
+
Returned solver can have error set in case of deal parser error, invalidate strain or leader (see @ref bcalcDDS_getLastError)
|
146
|
+
and in such case you should not use that solver.
|
147
|
+
In all cases constructed solver should be freed, after use, by @ref bcalcDDS_delete.
|
148
|
+
*/
|
149
|
+
extern BCalcDDS* bcalcDDS_new(const char* format, const char* hands, int strain, int leader);
|
150
|
+
|
151
|
+
/**
|
152
|
+
* Clone the state of the solver @p to_clone.
|
153
|
+
* @param to_clone solver to clone
|
154
|
+
* @return copy of @p to_clone or NULL (in case of out of memory, or if @p to_clone is NULL).
|
155
|
+
* Returned copy, as well as @p to_clone, must by freed, after use, by @ref bcalcDDS_delete
|
156
|
+
*/
|
157
|
+
extern BCalcDDS* bcalcDDS_clone(BCalcDDS* to_clone);
|
158
|
+
|
159
|
+
/**
|
160
|
+
Delete double dummy solver, free its memory.
|
161
|
+
@param solver constructed by @ref bcalcDDS_new, double dummy solver to delete, it is safe to pass NULL pointer (function do nothing in such a case)
|
162
|
+
*/
|
163
|
+
extern void bcalcDDS_delete(BCalcDDS* solver);
|
164
|
+
|
165
|
+
/**
|
166
|
+
Get last error string.
|
167
|
+
@param solver bcalc double dummy solver
|
168
|
+
@return last error message or NULL if no error, pointer to internal solver buffer (valid up to next bcalcDDS_* call for solver passed as argument)
|
169
|
+
*/
|
170
|
+
extern const char* bcalcDDS_getLastError(const BCalcDDS* solver);
|
171
|
+
|
172
|
+
/**
|
173
|
+
Clear error message.
|
174
|
+
|
175
|
+
After call, bcalcDDS_getLastError(solver) will return NULL.
|
176
|
+
@param solver bcalc double dummy solver
|
177
|
+
*/
|
178
|
+
extern void bcalcDDS_clearError(BCalcDDS* solver);
|
179
|
+
|
180
|
+
/**
|
181
|
+
Execute commands which can modify the state of given @p solver (current situation in game represented by it).
|
182
|
+
@param solver bcalc double dummy solver
|
183
|
+
@param cmds commands to execute
|
184
|
+
|
185
|
+
Commands should be separated by spaces and each can be one of:
|
186
|
+
- \<C\>\<S\> - where \<C\> is card symbol (like: A, Q, T, 6), \<S\> is suit symbol (one of: C, D, H, S), play choosen card
|
187
|
+
- x - play smallest possible card following played suit
|
188
|
+
- u - unplay one card
|
189
|
+
- ut - unplay last trick
|
190
|
+
- ua - unplay all tricks
|
191
|
+
*/
|
192
|
+
extern void bcalcDDS_exec(BCalcDDS* solver, const char* cmds);
|
193
|
+
|
194
|
+
/**
|
195
|
+
Calculate number of tricks possible to take (same as bcalcDDS_getTricksToTakeEx(solver, -1, 0)).
|
196
|
+
@param solver bcalc double dummy solver
|
197
|
+
@return number of tricks possible to take (in future) by line which plays in current situation
|
198
|
+
*/
|
199
|
+
extern int bcalcDDS_getTricksToTake(BCalcDDS* solver);
|
200
|
+
|
201
|
+
/**
|
202
|
+
If @p tricks_target == -1, calculate number of tricks possible to take.
|
203
|
+
If @p tricks_target >= 0 check if @p tricks_target number of tricks are possible to take.
|
204
|
+
Optionaly, if @c card != 0: it suppose that player to play starts with playing @c card.
|
205
|
+
@param solver bcalc double dummy solver
|
206
|
+
@param tricks_target (optional, -1 to ignore) target number of tricks to take by player to play
|
207
|
+
@param card if not 0 must include description of one card, held by player to play, in format: \<C\>\<S\> - where \<C\> is card symbol, \<S\> is suit symbol (can also be 'x' for smallest possible card following played suit)
|
208
|
+
@return
|
209
|
+
- If @p tricks_target == -1, it returns number of tricks possible to take (in future) by line which plays in current situation.
|
210
|
+
- If @p tricks_target >= 0, it returns 1 only if line which plays in current situation can take @p tricks_target tricks in future.
|
211
|
+
- In case of error (possible when @p card has wrong format) it returns -1.
|
212
|
+
*/
|
213
|
+
extern int bcalcDDS_getTricksToTakeEx(BCalcDDS* solver, int tricks_target, const char* card);
|
214
|
+
|
215
|
+
/**
|
216
|
+
Get strain.
|
217
|
+
@param solver bcalc double dummy solver
|
218
|
+
@return strain of game connected with @p solver
|
219
|
+
*/
|
220
|
+
extern int bcalcDDS_getTrump(BCalcDDS* solver);
|
221
|
+
|
222
|
+
/**
|
223
|
+
Set new strain and reset deal to initial state (undo all tricks).
|
224
|
+
@param solver bcalc double dummy solver
|
225
|
+
@param new_trump new strain to set for game connected with @p solver, one of BCALC_SUIT_* or BCALC_NT constant or ASCII symbol (one of: 'c', 'C', 'd', 'D', 'h', 'H', 's', 'S', 'n', 'N')
|
226
|
+
*/
|
227
|
+
extern void bcalcDDS_setTrumpAndReset(BCalcDDS* solver, int new_trump);
|
228
|
+
|
229
|
+
/**
|
230
|
+
Reset deal to initial state (undo all tricks) and change player on lead.
|
231
|
+
|
232
|
+
Note that this doesn't clear transposition table, so calculation results which was colecting with an other player on lead will be still use.
|
233
|
+
So if you need to iterate over all leader-strains pairs, and calculate number of tricks to take for each,
|
234
|
+
it is much more effective to iterate over strains in outer loop and over leaders in inner loop.
|
235
|
+
@param solver bcalc double dummy solver
|
236
|
+
@param new_leader player on lead, one of BCALC_PLAYER_* constant or player ASCII symbol (one of: 'n', 'N', 'e', 'E', 's', 'S', 'w', 'W')
|
237
|
+
*/
|
238
|
+
extern void bcalcDDS_setPlayerOnLeadAndReset(BCalcDDS* solver, int new_leader);
|
239
|
+
|
240
|
+
/**
|
241
|
+
Get numbers of tricks which have been already taken by players in game connected with @p solver.
|
242
|
+
@param solver bcalc double dummy solver
|
243
|
+
@param result buffer, array of minimum length of 4, place to store calculated numbers of tricks
|
244
|
+
@return @p result array, number of tricks taken by players, use BCALC_PLAYER_* as this array indexes
|
245
|
+
*/
|
246
|
+
extern int* bcalcDDS_getTricksTaken(BCalcDDS* solver, int* result);
|
247
|
+
|
248
|
+
/**
|
249
|
+
Get number of cards which left to play in game connected with @p solver.
|
250
|
+
@param solver bcalc double dummy solver
|
251
|
+
@return how many cards left to play to deal end, integer from 0 to 52
|
252
|
+
*/
|
253
|
+
extern int bcalcDDS_getCardsLeftCount(BCalcDDS* solver);
|
254
|
+
|
255
|
+
/**
|
256
|
+
Get cards owned by given @p player in given @p suit.
|
257
|
+
@param solver bcalc double dummy solver
|
258
|
+
@param player player, one of BCALC_PLAYER_* or player ASCII symbol (one of: 'n', 'N', 'e', 'E', 's', 'S', 'w', 'W')
|
259
|
+
@param suit suit, one of BCALC_SUIT_* or suit symbol in ASCII (one of: 'c', 'C', 'd', 'D', 'h', 'H', 's', 'S')
|
260
|
+
@param result buffer, place for results, safe length is 14 (13 cards and terminated zero)
|
261
|
+
@return @p result, zero-ended string, suits written using symbols from: AKQJT98765432,
|
262
|
+
in case of error @p result in unchanged form
|
263
|
+
*/
|
264
|
+
extern char* bcalcDDS_getCards(BCalcDDS* solver, char* result, int player, int suit);
|
265
|
+
|
266
|
+
/**
|
267
|
+
Get player which should play now.
|
268
|
+
@param solver bcalc double dummy solver
|
269
|
+
@return player which should play now in game connected with given @p solver
|
270
|
+
*/
|
271
|
+
extern int bcalcDDS_getPlayerToPlay(BCalcDDS* solver);
|
272
|
+
|
273
|
+
/**
|
274
|
+
Get cards possible to play in given @p suit by player who should play.
|
275
|
+
@param solver bcalc double dummy solver
|
276
|
+
@param result buffer, place for results, safe length is 14 (13 cards and terminated zero)
|
277
|
+
@param suit suit, one of BCALC_SUIT_* or suit symbol in ASCII (one of: 'c', 'C', 'd', 'D', 'h', 'H', 's', 'S')
|
278
|
+
@return @p result, zero-ended string, suits written using symbols from: AKQJT98765432,
|
279
|
+
in case of error @p result in unchanged form
|
280
|
+
*/
|
281
|
+
extern char* bcalcDDS_getCardsToPlay(BCalcDDS* solver, char* result, int suit);
|
282
|
+
|
283
|
+
/**
|
284
|
+
Get card played as a @p whenIndex (when card played on first lead has index 0).
|
285
|
+
@param solver bcalc double dummy solver
|
286
|
+
@param whenIndex card index, from 0 to @ref bcalcDDS_getPlayedCardsCount "bcalcDDS_getPlayedCardsCount(solver)"-1
|
287
|
+
@param suit place to save suit (if not NULL), one of BCALC_SUIT_*
|
288
|
+
@param cardSymbol place to store card symbol (if not NULL)
|
289
|
+
@return
|
290
|
+
- @c 1 only if card with given index was played,
|
291
|
+
- @c 0 if index is larger than @ref bcalcDDS_getPlayedCardsCount "bcalcDDS_getPlayedCardsCount(solver)"-1
|
292
|
+
(error is not set in such situation and @p suit and @p cardSymbol are not changed).
|
293
|
+
*/
|
294
|
+
extern int bcalcDDS_getPlayedCard(BCalcDDS* solver, unsigned whenIndex, int* suit, char* cardSymbol);
|
295
|
+
|
296
|
+
/**
|
297
|
+
Get number of cards which have been already played.
|
298
|
+
@param solver bcalc double dummy solver
|
299
|
+
@return number of cards which have been already played
|
300
|
+
*/
|
301
|
+
extern int bcalcDDS_getPlayedCardsCount(BCalcDDS* solver);
|
302
|
+
|
303
|
+
#ifdef __cplusplus
|
304
|
+
}
|
305
|
+
#endif
|
306
|
+
|
307
|
+
#endif //__BELING__BCALC_BRIDGE_SOLVER__
|
Binary file
|
Binary file
|
data/vendor/bcalc/test.c
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
#include "bcalcdds.h"
|
2
|
+
#include <stdio.h>
|
3
|
+
//check if solver is in error state, and if it is, print error message
|
4
|
+
void print_on_error(BCalcDDS* solver) {
|
5
|
+
const char* err = bcalcDDS_getLastError(solver);
|
6
|
+
if (err) printf("ERROR %s\n", err);
|
7
|
+
}
|
8
|
+
|
9
|
+
//print which player play now and how many tricks he can take
|
10
|
+
void print_tricks(BCalcDDS* solver) {
|
11
|
+
printf("%c playes, and he with partner will be able to take %d tricks.\n",
|
12
|
+
bcalc_playerSymbol(bcalcDDS_getPlayerToPlay(solver)),
|
13
|
+
bcalcDDS_getTricksToTake(solver)
|
14
|
+
);
|
15
|
+
print_on_error(solver);
|
16
|
+
}
|
17
|
+
|
18
|
+
//play all card in given suit and call print_tricks for situation after each play
|
19
|
+
void play(BCalcDDS* solver, int suit) {
|
20
|
+
char to_play[14];
|
21
|
+
bcalcDDS_getCardsToPlay(solver, to_play, suit);
|
22
|
+
printf("Cards possible to play in suit %c: %s\n", bcalc_suitSymbol(suit), to_play);
|
23
|
+
char play_cmd[3]; //string chars: card symbol, suit symbol, string termination zero
|
24
|
+
play_cmd[1] = bcalc_suitSymbol(suit);
|
25
|
+
play_cmd[2] = 0;
|
26
|
+
int i;
|
27
|
+
for (i = 0; to_play[i] != 0; ++i) {
|
28
|
+
play_cmd[0] = to_play[i];
|
29
|
+
printf(" After play %s: ", play_cmd);
|
30
|
+
bcalcDDS_exec(solver, play_cmd);
|
31
|
+
print_tricks(solver);
|
32
|
+
bcalcDDS_exec(solver, "u"); //undo
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
//call play for all suits
|
37
|
+
void play_all_suits(BCalcDDS* solver) {
|
38
|
+
print_tricks(solver);
|
39
|
+
int suit;
|
40
|
+
for (suit = 0; suit < 4; ++suit)
|
41
|
+
play(solver, suit);
|
42
|
+
}
|
43
|
+
|
44
|
+
//print number of tricks possible to take and all best moves
|
45
|
+
void find_best_moves(BCalcDDS* solver) {
|
46
|
+
int target = bcalcDDS_getTricksToTake(solver);
|
47
|
+
printf("%c playes, and he with partner will be able to take %d tricks by play:",
|
48
|
+
bcalc_playerSymbol(bcalcDDS_getPlayerToPlay(solver)), target
|
49
|
+
);
|
50
|
+
int suit;
|
51
|
+
char card_to_play[3]; //<rank><suit><null>
|
52
|
+
card_to_play[2] = 0;
|
53
|
+
for (suit = 0; suit < 4; ++suit) {
|
54
|
+
card_to_play[1] = bcalc_suitSymbol(suit);
|
55
|
+
char all_cards_to_play[14];
|
56
|
+
bcalcDDS_getCardsToPlay(solver, all_cards_to_play, suit);
|
57
|
+
int i;
|
58
|
+
for (i = 0; all_cards_to_play[i] != 0; ++i) {
|
59
|
+
card_to_play[0] = all_cards_to_play[i];
|
60
|
+
if (bcalcDDS_getTricksToTakeEx(solver, target, card_to_play))
|
61
|
+
printf(" %s", card_to_play);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
printf("\n");
|
65
|
+
}
|
66
|
+
|
67
|
+
int main() {
|
68
|
+
BCalcDDS* solver = bcalcDDS_new("PBN", "N:.63.AKQ987.A9732 A8654.KQ5.T.QJT6 J973.J98742.3.K4 KQT2.AT.J6542.85", BCALC_NT, BCALC_PLAYER_NORTH);
|
69
|
+
if (!solver) {
|
70
|
+
printf("Can't create solver!");
|
71
|
+
return 1;
|
72
|
+
}
|
73
|
+
print_on_error(solver);
|
74
|
+
|
75
|
+
play_all_suits(solver);
|
76
|
+
find_best_moves(solver);
|
77
|
+
|
78
|
+
char* to_play = "7D x x";
|
79
|
+
printf("\nPlay some cards: %s\n", to_play);
|
80
|
+
bcalcDDS_exec(solver, to_play);
|
81
|
+
print_on_error(solver);
|
82
|
+
play_all_suits(solver);
|
83
|
+
find_best_moves(solver);
|
84
|
+
|
85
|
+
bcalcDDS_delete(solver);
|
86
|
+
|
87
|
+
return 0;
|
88
|
+
}
|
Binary file
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rbcalc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Achilles Charmpilas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: RubyInline
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.12'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.12'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fuubar
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Ruby bindings for Piotr Beling's Bridge Calculator
|
84
|
+
email:
|
85
|
+
- ac@humbuckercode.co.uk
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/rbcalc.rb
|
96
|
+
- lib/rbcalc/engine.rb
|
97
|
+
- lib/rbcalc/version.rb
|
98
|
+
- rbcalc.gemspec
|
99
|
+
- spec/rbcalc_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
- vendor/bcalc/bcalcdds.h
|
102
|
+
- vendor/bcalc/libbcalcdds.dylib
|
103
|
+
- vendor/bcalc/libbcalcdds.so
|
104
|
+
- vendor/bcalc/test.c
|
105
|
+
- vendor/bcalc/win32/libbcalcdds.dll
|
106
|
+
- vendor/bcalc/win64/libbcalcdds.dll
|
107
|
+
homepage: ''
|
108
|
+
licenses:
|
109
|
+
- MIT
|
110
|
+
metadata: {}
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 2.1.11
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: Ruby bindings for Piotr Beling's Bridge Calculator
|
131
|
+
test_files:
|
132
|
+
- spec/rbcalc_spec.rb
|
133
|
+
- spec/spec_helper.rb
|