rbcalc 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|