rbcalc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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=
@@ -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
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rbcalc.gemspec
4
+ gemspec
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.
@@ -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
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -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
@@ -0,0 +1,3 @@
1
+ module Rbcalc
2
+ VERSION = "0.1.0"
3
+ end
@@ -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
@@ -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
@@ -0,0 +1,10 @@
1
+ require 'rbcalc'
2
+ root = File.dirname(__FILE__)
3
+
4
+ #Dir[File.join(root,'support', '**','*.rb')].each { |f| require f }
5
+
6
+ RSpec.configure do |config|
7
+ config.color_enabled = true
8
+ config.mock_with :rspec
9
+ config.order = "random"
10
+ end
@@ -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__
@@ -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
+ }
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