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.
@@ -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