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