1 /*
2 Copyright © 2007, 2008 Christian Persch
3
4 This library is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <config.h>
19
20 #include <glib/gi18n.h>
21
22 #include "ar-card.h"
23 #include "ar-card-private.h"
24
25 static const char extra_cards[] =
26 "joker_black\0"
27 "joker_red\0"
28 "back\0"
29 "slot";
30 static const guint8 extra_card_offsets[] = {
31 0, 12, 22, 27
32 };
33
34 static const char suites[] =
35 "club\0"
36 "diamond\0"
37 "heart\0"
38 "spade";
39 static const guint8 suite_offsets[] = {
40 0, 5, 13, 19
41 };
42
43 static const char ranks[] =
44 "1\0"
45 "2\0"
46 "3\0"
47 "4\0"
48 "5\0"
49 "6\0"
50 "7\0"
51 "8\0"
52 "9\0"
53 "10\0"
54 "jack\0"
55 "queen\0"
56 "king";
57 static const guint8 rank_offsets[] = {
58 0, 2, 4, 6, 8, 10, 12, 14,
59 16, 18, 21, 26, 32
60 };
61
62 /**
63 * ar_card_get_node_by_suit_and_rank_snprintf:
64 * @buffer: the output buffer
65 * @bufsize: the size of the output buffer
66 * @suit: the suit of the card
67 * @rank: the rank of the card
68 *
69 * Prints the identifier for the card @card into @buffer.
70 *
71 * Returns: the number of bytes which would be produced if the buffer
72 * was large enough.
73 */
74 int
ar_card_get_node_by_suit_and_rank_snprintf(char * buffer,gsize bufsize,int suit,int rank)75 ar_card_get_node_by_suit_and_rank_snprintf (char *buffer,
76 gsize bufsize,
77 int suit,
78 int rank)
79 {
80 int len;
81
82 if (G_LIKELY (suit < 4)) {
83 len = g_snprintf (buffer, bufsize, "#%s_%s",
84 suites + suite_offsets[suit],
85 ranks + rank_offsets[rank]);
86 } else {
87 len = g_snprintf (buffer, bufsize, "#%s",
88 extra_cards + extra_card_offsets[rank]);
89 }
90
91 return len;
92 }
93
94
95 /**
96 * ar_card_get_legacy_node_by_suit_and_rank_snprintf:
97 * @buffer: the output buffer
98 * @bufsize: the size of the output buffer
99 * @suit: the suit of the card
100 * @rank: the rank of the card
101 *
102 * Prints the legacy identifier for the card @card into @buffer.
103 *
104 * Returns: the number of bytes which would be produced if the buffer
105 * was large enough.
106 */
107 int
ar_card_get_legacy_node_by_suit_and_rank_snprintf(char * buffer,gsize bufsize,int suit,int rank)108 ar_card_get_legacy_node_by_suit_and_rank_snprintf (char *buffer,
109 gsize bufsize,
110 int suit,
111 int rank)
112 {
113 int len;
114
115 if (G_LIKELY (suit < 4)) {
116 len = g_snprintf (buffer, bufsize, "#%s_%s",
117 ranks + rank_offsets[rank],
118 suites + suite_offsets[suit]);
119 } else {
120 len = g_snprintf (buffer, bufsize, "#%s",
121 extra_cards + extra_card_offsets[rank]);
122 }
123
124 return len;
125 }
126
127 /**
128 * ar_card_get_node_by_id_snprintf:
129 * @buffer: the output buffer
130 * @bufsize: the size of the output buffer
131 * @card_id: the ID of the card
132 *
133 * Prints the identifier for the card @card into @buffer.
134 *
135 * Returns: the number of bytes which would be produced if the buffer
136 * was large enough.
137 */
138 int
ar_card_get_node_by_id_snprintf(char * buffer,gsize bufsize,int card_id)139 ar_card_get_node_by_id_snprintf (char *buffer,
140 gsize bufsize,
141 int card_id)
142 {
143 int suit, rank;
144
145 suit = card_id / 13;
146 rank = card_id % 13;
147
148 return ar_card_get_node_by_suit_and_rank_snprintf (buffer, bufsize, suit, rank);
149 }
150
151 /**
152 * ar_card_get_legacy_node_by_id_snprintf:
153 * @buffer: the output buffer
154 * @bufsize: the size of the output buffer
155 * @card_id: the ID of the card
156 *
157 * Prints the legacy identifier for the card @card into @buffer.
158 *
159 * Returns: the number of bytes which would be produced if the buffer
160 * was large enough.
161 */
162 int
ar_card_get_legacy_node_by_id_snprintf(char * buffer,gsize bufsize,int card_id)163 ar_card_get_legacy_node_by_id_snprintf (char *buffer,
164 gsize bufsize,
165 int card_id)
166 {
167 int suit, rank;
168
169 suit = card_id / 13;
170 rank = card_id % 13;
171
172 return ar_card_get_legacy_node_by_suit_and_rank_snprintf (buffer, bufsize, suit, rank);
173 }
174
175 /**
176 * ar_card_get_name_by_id_snprintf:
177 * @buffer: the output buffer
178 * @bufsize: the size of the output buffer
179 * @card_id: the ID of the card
180 *
181 * Prints the identifier for the card @card into @buffer.
182 *
183 * Returns: the number of bytes which would be produced if the buffer
184 * was large enough.
185 */
186 int
ar_card_get_name_by_id_snprintf(char * buffer,gsize bufsize,int card_id)187 ar_card_get_name_by_id_snprintf (char *buffer,
188 gsize bufsize,
189 int card_id)
190 {
191 int suit, rank, len;
192
193 suit = card_id / 13;
194 rank = card_id % 13;
195
196 if (G_LIKELY (suit < 4)) {
197 len = g_snprintf (buffer, bufsize, "%s-%s",
198 suites + suite_offsets[suit],
199 ranks + rank_offsets[rank]);
200 } else {
201 len = g_snprintf (buffer, bufsize, "%s",
202 extra_cards + extra_card_offsets[rank]);
203 }
204
205 return len;
206 }
207
208 /**
209 * ar_card_get_name_by_id:
210 * @card_id:
211 *
212 * Returns the name of the card @cardid
213 *
214 * Returns: a newly allocated string containing the identifier for @card_id
215 */
216 char *
ar_card_get_name_by_id(gint card_id)217 ar_card_get_name_by_id (gint card_id)
218 {
219 char name[128];
220
221 ar_card_get_name_by_id_snprintf (name, sizeof (name), card_id);
222
223 return g_strdup (name);
224 }
225
226 /**
227 * ar_card_get_localised_rank_symbol:
228 * @rank: the card rank
229 *
230 * Returns: the localised rank card symbol
231 */
232 const char *
ar_card_get_localised_rank_symbol(int rank)233 ar_card_get_localised_rank_symbol (int rank)
234 {
235 static const char *rank_texts[] = {
236 /* Translators: this is the symbol that's on a Joker card */
237 NC_("card symbol", "JOKER"),
238 /* Translators: this is the symbol that's on an Ace card */
239 NC_("card symbol", "A"),
240 /* Translators: this is the symbol that's on a 2 card */
241 NC_("card symbol", "2"),
242 /* Translators: this is the symbol that's on a 3 card */
243 NC_("card symbol", "3"),
244 /* Translators: this is the symbol that's on a 4 card */
245 NC_("card symbol", "4"),
246 /* Translators: this is the symbol that's on a 5 card */
247 NC_("card symbol", "5"),
248 /* Translators: this is the symbol that's on a 6 card */
249 NC_("card symbol", "6"),
250 /* Translators: this is the symbol that's on a 7 card */
251 NC_("card symbol", "7"),
252 /* Translators: this is the symbol that's on a 8 card */
253 NC_("card symbol", "8"),
254 /* Translators: this is the symbol that's on a 9 card */
255 NC_("card symbol", "9"),
256 /* Translators: this is the symbol that's on a Jack card */
257 NC_("card symbol", "J"),
258 /* Translators: this is the symbol that's on a Queen card */
259 NC_("card symbol", "Q"),
260 /* Translators: this is the symbol that's on a King card */
261 NC_("card symbol", "K"),
262 /* Translators: this is the symbol that's on an Ace card */
263 NC_("card symbol", "A"),
264 /* Translators: this is the symbol that's on a 1 card */
265 NC_("card symbol", "1")
266 };
267
268 g_return_val_if_fail (rank >= AR_CARD_JOKER && rank <= AR_CARD_ACE_HIGH, NULL);
269
270 return g_dpgettext2 (GETTEXT_PACKAGE, "card symbol", rank_texts[rank]);
271 }
272
273 guint
_ar_card_to_index(Card card)274 _ar_card_to_index (Card card)
275 {
276 guint card_id;
277
278 if (CARD_GET_FACE_DOWN (card)) {
279 card_id = AR_CARD_BACK;
280 } else if (G_UNLIKELY (CARD_GET_RANK (card) == 0)) {
281 /* A joker */
282 if (CARD_GET_SUIT (card) == AR_CARDS_CLUBS ||
283 CARD_GET_SUIT (card) == AR_CARDS_SPADES) {
284 /* A black joker. */
285 card_id = AR_CARD_BLACK_JOKER;
286 } else {
287 /* A red joker. */
288 card_id = AR_CARD_RED_JOKER;
289 }
290 } else {
291 card_id = AR_CARD_ID (CARD_GET_SUIT (card), CARD_GET_RANK (card));
292 }
293
294 return card_id;
295 }
296
297 /* FIXMEchpe compactify & constify */
298 static const char *card_names[] = {
299 N_("ace of clubs"),
300 N_("two of clubs"),
301 N_("three of clubs"),
302 N_("four of clubs"),
303 N_("five of clubs"),
304 N_("six of clubs"),
305 N_("seven of clubs"),
306 N_("eight of clubs"),
307 N_("nine of clubs"),
308 N_("ten of clubs"),
309 N_("jack of clubs"),
310 N_("queen of clubs"),
311 N_("king of clubs"),
312 N_("ace of diamonds"),
313 N_("two of diamonds"),
314 N_("three of diamonds"),
315 N_("four of diamonds"),
316 N_("five of diamonds"),
317 N_("six of diamonds"),
318 N_("seven of diamonds"),
319 N_("eight of diamonds"),
320 N_("nine of diamonds"),
321 N_("ten of diamonds"),
322 N_("jack of diamonds"),
323 N_("queen of diamonds"),
324 N_("king of diamonds"),
325 N_("ace of hearts"),
326 N_("two of hearts"),
327 N_("three of hearts"),
328 N_("four of hearts"),
329 N_("five of hearts"),
330 N_("six of hearts"),
331 N_("seven of hearts"),
332 N_("eight of hearts"),
333 N_("nine of hearts"),
334 N_("ten of hearts"),
335 N_("jack of hearts"),
336 N_("queen of hearts"),
337 N_("king of hearts"),
338 N_("ace of spades"),
339 N_("two of spades"),
340 N_("three of spades"),
341 N_("four of spades"),
342 N_("five of spades"),
343 N_("six of spades"),
344 N_("seven of spades"),
345 N_("eight of spades"),
346 N_("nine of spades"),
347 N_("ten of spades"),
348 N_("jack of spades"),
349 N_("queen of spades"),
350 N_("king of spades")
351 };
352 #define AR_CARD_ID(suit, rank) ((13*(suit)) + ((rank-1)%13))
353
354 /**
355 * ar_card_get_localized_name:
356 * @card:
357 *
358 * Returns: a localised name for @card, e.g. "Face-down card" or
359 * "9 of clubs", etc.
360 */
361 const char *
ar_card_get_locale_name(Card card)362 ar_card_get_locale_name (Card card)
363 {
364 guint rank, suit;
365
366 if (CARD_GET_FACE_DOWN (card)) {
367 return _("face-down card");
368 };
369
370 rank = CARD_GET_RANK (card);
371 suit = CARD_GET_SUIT (card);
372
373 if (G_UNLIKELY (rank == 0)) {
374 /* A joker */
375 if (suit == AR_CARDS_CLUBS ||
376 suit == AR_CARDS_SPADES) {
377 /* A black joker. */
378 return _("black joker");
379 } else {
380 /* A red joker. */
381 return _("red joker");
382 }
383 }
384
385 return _(card_names[AR_CARD_ID(suit, rank)]);
386 }
387