#include #include #include "mjp.h" #include "tiles.h" int whitespace(unsigned char ch) { switch (ch) { case ' ': case '\t': case '\n': return(1); } return(0); } #if NWIND != 4 #error pidx() needs updating #endif int pidx(unsigned char ch) { switch (ch) { default: return(-1); break; case '1': return(0); break; case '2': return(1); break; case '3': return(2); break; case '4': return(3); break; } } #if NWIND != 4 #error pxid() needs updating #endif unsigned char pxid(int x) { switch (x) { case 0: return('1'); break; case 1: return('2'); break; case 2: return('3'); break; case 3: return('4'); break; } abort(); } #if NWIND != 4 #error charwind() needs updating #endif int charwind(unsigned char ch) { switch (ch) { default: return(WIND_BAD); break; case '?': return(WIND_NONE); break; case 'e': case 'E': return(WIND_E); break; case 'w': case 'W': return(WIND_W); break; case 'n': case 'N': return(WIND_N); break; case 's': case 'S': return(WIND_S); break; } } #if NWIND != 4 #error windchar() needs updating #endif unsigned char windchar(int w) { switch (w) { case WIND_E: return('E'); break; case WIND_W: return('W'); break; case WIND_N: return('N'); break; case WIND_S: return('S'); break; } abort(); } #if NWIND != 4 #error xwindchar() needs updating #endif unsigned char xwindchar(int w) { switch (w) { case WIND_E: return('E'); break; case WIND_W: return('W'); break; case WIND_N: return('N'); break; case WIND_S: return('S'); break; case WIND_NONE: return('?'); break; } abort(); } PLACE makeplace(PLACETYPE key, ...) { va_list ap; PLACE p; p.type = key; va_start(ap,key); switch (key) { default: abort(); break; case PT_DECK: break; case PT_WALL: p.wall = va_arg(ap,int); if ((p.wall < 0) || (p.wall >= WALLSIZE)) abort(); break; case PT_HAND: p.hand = va_arg(ap,int); if ((p.hand < 0) || (p.hand >= NWIND)) abort(); break; case PT_FS: p.fs = va_arg(ap,int); if ((p.fs < 0) || (p.fs >= NWIND)) abort(); break; case PT_REPL: p.repl = va_arg(ap,int); if ((p.repl < 0) || (p.repl >= REPLSIZE)) abort(); break; case PT_DORA: p.dora = va_arg(ap,int); if ((p.dora < 0) || (p.dora >= DORASIZE)) abort(); break; case PT_DISC: p.disc = va_arg(ap,int); if ((p.disc < 0) || (p.disc >= NWIND)) abort(); break; case PT_MELD: p.meld.h = va_arg(ap,int); if ((p.meld.h < 0) || (p.meld.h >= NWIND)) abort(); p.meld.m = va_arg(ap,int); if ((p.meld.m < 0) || (p.meld.m >= MAXMELDS)) abort(); break; } va_end(ap); return(p); } const unsigned char magic_server[MJP_MAGICLEN] = "mmj1s"; const unsigned char magic_client[MJP_MAGICLEN] = "mmj1c"; const TILE unshuffled_deck[] = { TILE_1_BAMBOO, TILE_1_CHARACTER, TILE_1_DOT, TILE_WIND_E, TILE_1_BAMBOO, TILE_1_CHARACTER, TILE_1_DOT, TILE_WIND_E, TILE_1_BAMBOO, TILE_1_CHARACTER, TILE_1_DOT, TILE_WIND_E, TILE_1_BAMBOO, TILE_1_CHARACTER, TILE_1_DOT, TILE_WIND_E, TILE_2_BAMBOO, TILE_2_CHARACTER, TILE_2_DOT, TILE_WIND_S, TILE_2_BAMBOO, TILE_2_CHARACTER, TILE_2_DOT, TILE_WIND_S, TILE_2_BAMBOO, TILE_2_CHARACTER, TILE_2_DOT, TILE_WIND_S, TILE_2_BAMBOO, TILE_2_CHARACTER, TILE_2_DOT, TILE_WIND_S, TILE_3_BAMBOO, TILE_3_CHARACTER, TILE_3_DOT, TILE_WIND_W, TILE_3_BAMBOO, TILE_3_CHARACTER, TILE_3_DOT, TILE_WIND_W, TILE_3_BAMBOO, TILE_3_CHARACTER, TILE_3_DOT, TILE_WIND_W, TILE_3_BAMBOO, TILE_3_CHARACTER, TILE_3_DOT, TILE_WIND_W, TILE_4_BAMBOO, TILE_4_CHARACTER, TILE_4_DOT, TILE_WIND_N, TILE_4_BAMBOO, TILE_4_CHARACTER, TILE_4_DOT, TILE_WIND_N, TILE_4_BAMBOO, TILE_4_CHARACTER, TILE_4_DOT, TILE_WIND_N, TILE_4_BAMBOO, TILE_4_CHARACTER, TILE_4_DOT, TILE_WIND_N, TILE_5_BAMBOO, TILE_5_CHARACTER, TILE_5_DOT, TILE_DRAGON_R, TILE_5_BAMBOO, TILE_5_CHARACTER, TILE_5_DOT, TILE_DRAGON_R, TILE_5_BAMBOO, TILE_5_CHARACTER, TILE_5_DOT, TILE_DRAGON_R, TILE_5_BAMBOO, TILE_5_CHARACTER, TILE_5_DOT, TILE_DRAGON_R, TILE_6_BAMBOO, TILE_6_CHARACTER, TILE_6_DOT, TILE_DRAGON_G, TILE_6_BAMBOO, TILE_6_CHARACTER, TILE_6_DOT, TILE_DRAGON_G, TILE_6_BAMBOO, TILE_6_CHARACTER, TILE_6_DOT, TILE_DRAGON_G, TILE_6_BAMBOO, TILE_6_CHARACTER, TILE_6_DOT, TILE_DRAGON_G, TILE_7_BAMBOO, TILE_7_CHARACTER, TILE_7_DOT, TILE_DRAGON_W, TILE_7_BAMBOO, TILE_7_CHARACTER, TILE_7_DOT, TILE_DRAGON_W, TILE_7_BAMBOO, TILE_7_CHARACTER, TILE_7_DOT, TILE_DRAGON_W, TILE_7_BAMBOO, TILE_7_CHARACTER, TILE_7_DOT, TILE_DRAGON_W, TILE_8_BAMBOO, TILE_8_CHARACTER, TILE_8_DOT, TILE_HAKU, TILE_8_BAMBOO, TILE_8_CHARACTER, TILE_8_DOT, TILE_HAKU, TILE_8_BAMBOO, TILE_8_CHARACTER, TILE_8_DOT, TILE_HAKU, TILE_8_BAMBOO, TILE_8_CHARACTER, TILE_8_DOT, TILE_HAKU, TILE_9_BAMBOO, TILE_9_CHARACTER, TILE_9_DOT, TILE_FLOWER_A, TILE_9_BAMBOO, TILE_9_CHARACTER, TILE_9_DOT, TILE_FLOWER_B, TILE_9_BAMBOO, TILE_9_CHARACTER, TILE_9_DOT, TILE_FLOWER_C, TILE_9_BAMBOO, TILE_9_CHARACTER, TILE_9_DOT, TILE_FLOWER_D, TILE_SEASON_A, TILE_SEASON_B, TILE_SEASON_C, TILE_SEASON_D }; const char * const tilenames[TILE__N] = { [TILE_1_BAMBOO] = "b1", [TILE_1_CHARACTER] = "c1", [TILE_1_DOT] = "d1", [TILE_2_BAMBOO] = "b2", [TILE_2_CHARACTER] = "c2", [TILE_2_DOT] = "d2", [TILE_3_BAMBOO] = "b3", [TILE_3_CHARACTER] = "c3", [TILE_3_DOT] = "d3", [TILE_4_BAMBOO] = "b4", [TILE_4_CHARACTER] = "c4", [TILE_4_DOT] = "d4", [TILE_5_BAMBOO] = "b5", [TILE_5_CHARACTER] = "c5", [TILE_5_DOT] = "d5", [TILE_6_BAMBOO] = "b6", [TILE_6_CHARACTER] = "c6", [TILE_6_DOT] = "d6", [TILE_7_BAMBOO] = "b7", [TILE_7_CHARACTER] = "c7", [TILE_7_DOT] = "d7", [TILE_8_BAMBOO] = "b8", [TILE_8_CHARACTER] = "c8", [TILE_8_DOT] = "d8", [TILE_9_BAMBOO] = "b9", [TILE_9_CHARACTER] = "c9", [TILE_9_DOT] = "d9", [TILE_DRAGON_G] = "dg", [TILE_DRAGON_R] = "dr", [TILE_DRAGON_W] = "dw", [TILE_FLOWER_A] = "f1", [TILE_SEASON_A] = "s1", [TILE_WIND_E] = "we", [TILE_FLOWER_B] = "f2", [TILE_SEASON_B] = "s2", [TILE_WIND_N] = "wn", [TILE_FLOWER_C] = "f3", [TILE_SEASON_C] = "s3", [TILE_WIND_S] = "ws", [TILE_FLOWER_D] = "f4", [TILE_SEASON_D] = "s4", [TILE_WIND_W] = "ww", [TILE_HAKU] = "h" }; unsigned short int tileflags_[TILE__N] #define ONE TF_TERMINAL | TF_LOWER3 | TF_LOWER4 #define TWO TF_SIMPLE | TF_LOWER3 | TF_LOWER4 | TF_EVEN #define THREE TF_SIMPLE | TF_LOWER3 | TF_LOWER4 #define FOUR TF_SIMPLE | TF_MIDDLE3 | TF_LOWER4 | TF_EVEN #define FIVE TF_SIMPLE | TF_MIDDLE3 | TF_FIVE #define SIX TF_SIMPLE | TF_MIDDLE3 | TF_UPPER4 | TF_EVEN #define SEVEN TF_SIMPLE | TF_UPPER3 | TF_UPPER4 #define EIGHT TF_SIMPLE | TF_UPPER3 | TF_UPPER4 | TF_EVEN #define NINE TF_TERMINAL | TF_UPPER3 | TF_UPPER4 = { [TILE_1_BAMBOO] = ONE, [TILE_1_CHARACTER] = ONE, [TILE_1_DOT] = ONE | TF_REVERSIBLE, [TILE_2_BAMBOO] = TWO | TF_GREEN | TF_REVERSIBLE, [TILE_2_CHARACTER] = TWO, [TILE_2_DOT] = TWO | TF_REVERSIBLE, [TILE_3_BAMBOO] = THREE | TF_GREEN, [TILE_3_CHARACTER] = THREE, [TILE_3_DOT] = THREE | TF_REVERSIBLE, [TILE_4_BAMBOO] = FOUR | TF_GREEN | TF_REVERSIBLE, [TILE_4_CHARACTER] = FOUR, [TILE_4_DOT] = FOUR | TF_REVERSIBLE, [TILE_5_BAMBOO] = FIVE | TF_REVERSIBLE, [TILE_5_CHARACTER] = FIVE, [TILE_5_DOT] = FIVE | TF_REVERSIBLE, [TILE_6_BAMBOO] = SIX | TF_GREEN | TF_REVERSIBLE, [TILE_6_CHARACTER] = SIX, [TILE_6_DOT] = SIX, [TILE_7_BAMBOO] = SEVEN, [TILE_7_CHARACTER] = SEVEN, [TILE_7_DOT] = SEVEN, [TILE_8_BAMBOO] = EIGHT | TF_GREEN | TF_REVERSIBLE, [TILE_8_CHARACTER] = EIGHT, [TILE_8_DOT] = EIGHT | TF_REVERSIBLE, [TILE_9_BAMBOO] = NINE | TF_REVERSIBLE, [TILE_9_CHARACTER] = NINE, [TILE_9_DOT] = NINE | TF_REVERSIBLE, [TILE_DRAGON_G] = TF_DRAGON | TF_GREEN, [TILE_DRAGON_R] = TF_DRAGON, [TILE_DRAGON_W] = TF_DRAGON | TF_REVERSIBLE, [TILE_FLOWER_A] = TF_FS, [TILE_FLOWER_B] = TF_FS, [TILE_FLOWER_C] = TF_FS, [TILE_FLOWER_D] = TF_FS, [TILE_HAKU] = TF_DRAGON | TF_REVERSIBLE, [TILE_SEASON_A] = TF_FS, [TILE_SEASON_B] = TF_FS, [TILE_SEASON_C] = TF_FS, [TILE_SEASON_D] = TF_FS, [TILE_WIND_E] = TF_WIND, [TILE_WIND_N] = TF_WIND, [TILE_WIND_S] = TF_WIND, [TILE_WIND_W] = TF_WIND }; #undef ONE #undef TWO #undef THREE #undef FOUR #undef FIVE #undef SIX #undef SEVEN #undef EIGHT #undef NINE TILE tile_nextup_[TILE__N] = { [TILE_1_BAMBOO] = TILE_2_BAMBOO, [TILE_1_CHARACTER] = TILE_2_CHARACTER, [TILE_1_DOT] = TILE_2_DOT, [TILE_2_BAMBOO] = TILE_3_BAMBOO, [TILE_2_CHARACTER] = TILE_3_CHARACTER, [TILE_2_DOT] = TILE_3_DOT, [TILE_3_BAMBOO] = TILE_4_BAMBOO, [TILE_3_CHARACTER] = TILE_4_CHARACTER, [TILE_3_DOT] = TILE_4_DOT, [TILE_4_BAMBOO] = TILE_5_BAMBOO, [TILE_4_CHARACTER] = TILE_5_CHARACTER, [TILE_4_DOT] = TILE_5_DOT, [TILE_5_BAMBOO] = TILE_6_BAMBOO, [TILE_5_CHARACTER] = TILE_6_CHARACTER, [TILE_5_DOT] = TILE_6_DOT, [TILE_6_BAMBOO] = TILE_7_BAMBOO, [TILE_6_CHARACTER] = TILE_7_CHARACTER, [TILE_6_DOT] = TILE_7_DOT, [TILE_7_BAMBOO] = TILE_8_BAMBOO, [TILE_7_CHARACTER] = TILE_8_CHARACTER, [TILE_7_DOT] = TILE_8_DOT, [TILE_8_BAMBOO] = TILE_9_BAMBOO, [TILE_8_CHARACTER] = TILE_9_CHARACTER, [TILE_8_DOT] = TILE_9_DOT, [TILE_9_BAMBOO] = TILE_NOTILE, [TILE_9_CHARACTER] = TILE_NOTILE, [TILE_9_DOT] = TILE_NOTILE, [TILE_DRAGON_G] = TILE_NOTILE, [TILE_DRAGON_R] = TILE_NOTILE, [TILE_DRAGON_W] = TILE_NOTILE, [TILE_FLOWER_A] = TILE_NOTILE, [TILE_FLOWER_B] = TILE_NOTILE, [TILE_FLOWER_C] = TILE_NOTILE, [TILE_FLOWER_D] = TILE_NOTILE, [TILE_HAKU] = TILE_NOTILE, [TILE_SEASON_A] = TILE_NOTILE, [TILE_SEASON_B] = TILE_NOTILE, [TILE_SEASON_C] = TILE_NOTILE, [TILE_SEASON_D] = TILE_NOTILE, [TILE_WIND_E] = TILE_NOTILE, [TILE_WIND_N] = TILE_NOTILE, [TILE_WIND_S] = TILE_NOTILE, [TILE_WIND_W] = TILE_NOTILE }; TILE tile_nextdn_[TILE__N] = { [TILE_1_BAMBOO] = TILE_NOTILE, [TILE_1_CHARACTER] = TILE_NOTILE, [TILE_1_DOT] = TILE_NOTILE, [TILE_2_BAMBOO] = TILE_1_BAMBOO, [TILE_2_CHARACTER] = TILE_1_CHARACTER, [TILE_2_DOT] = TILE_1_DOT, [TILE_3_BAMBOO] = TILE_2_BAMBOO, [TILE_3_CHARACTER] = TILE_2_CHARACTER, [TILE_3_DOT] = TILE_2_DOT, [TILE_4_BAMBOO] = TILE_3_BAMBOO, [TILE_4_CHARACTER] = TILE_3_CHARACTER, [TILE_4_DOT] = TILE_3_DOT, [TILE_5_BAMBOO] = TILE_4_BAMBOO, [TILE_5_CHARACTER] = TILE_4_CHARACTER, [TILE_5_DOT] = TILE_4_DOT, [TILE_6_BAMBOO] = TILE_5_BAMBOO, [TILE_6_CHARACTER] = TILE_5_CHARACTER, [TILE_6_DOT] = TILE_5_DOT, [TILE_7_BAMBOO] = TILE_6_BAMBOO, [TILE_7_CHARACTER] = TILE_6_CHARACTER, [TILE_7_DOT] = TILE_6_DOT, [TILE_8_BAMBOO] = TILE_7_BAMBOO, [TILE_8_CHARACTER] = TILE_7_CHARACTER, [TILE_8_DOT] = TILE_7_DOT, [TILE_9_BAMBOO] = TILE_8_BAMBOO, [TILE_9_CHARACTER] = TILE_8_CHARACTER, [TILE_9_DOT] = TILE_8_DOT, [TILE_DRAGON_G] = TILE_NOTILE, [TILE_DRAGON_R] = TILE_NOTILE, [TILE_DRAGON_W] = TILE_NOTILE, [TILE_FLOWER_A] = TILE_NOTILE, [TILE_FLOWER_B] = TILE_NOTILE, [TILE_FLOWER_C] = TILE_NOTILE, [TILE_FLOWER_D] = TILE_NOTILE, [TILE_HAKU] = TILE_NOTILE, [TILE_SEASON_A] = TILE_NOTILE, [TILE_SEASON_B] = TILE_NOTILE, [TILE_SEASON_C] = TILE_NOTILE, [TILE_SEASON_D] = TILE_NOTILE, [TILE_WIND_E] = TILE_NOTILE, [TILE_WIND_N] = TILE_NOTILE, [TILE_WIND_S] = TILE_NOTILE, [TILE_WIND_W] = TILE_NOTILE }; int tile_num_[TILE__N] = { [TILE_1_BAMBOO] = 1, [TILE_1_CHARACTER] = 1, [TILE_1_DOT] = 1, [TILE_2_BAMBOO] = 2, [TILE_2_CHARACTER] = 2, [TILE_2_DOT] = 2, [TILE_3_BAMBOO] = 3, [TILE_3_CHARACTER] = 3, [TILE_3_DOT] = 3, [TILE_4_BAMBOO] = 4, [TILE_4_CHARACTER] = 4, [TILE_4_DOT] = 4, [TILE_5_BAMBOO] = 5, [TILE_5_CHARACTER] = 5, [TILE_5_DOT] = 5, [TILE_6_BAMBOO] = 6, [TILE_6_CHARACTER] = 6, [TILE_6_DOT] = 6, [TILE_7_BAMBOO] = 7, [TILE_7_CHARACTER] = 7, [TILE_7_DOT] = 7, [TILE_8_BAMBOO] = 8, [TILE_8_CHARACTER] = 8, [TILE_8_DOT] = 8, [TILE_9_BAMBOO] = 9, [TILE_9_CHARACTER] = 9, [TILE_9_DOT] = 9, [TILE_DRAGON_G] = -1, [TILE_DRAGON_R] = -1, [TILE_DRAGON_W] = -1, [TILE_FLOWER_A] = -1, [TILE_FLOWER_B] = -1, [TILE_FLOWER_C] = -1, [TILE_FLOWER_D] = -1, [TILE_HAKU] = -1, [TILE_SEASON_A] = -1, [TILE_SEASON_B] = -1, [TILE_SEASON_C] = -1, [TILE_SEASON_D] = -1, [TILE_WIND_E] = -1, [TILE_WIND_N] = -1, [TILE_WIND_S] = -1, [TILE_WIND_W] = -1 }; TILE wind_to_tile_[NWIND] = { [WIND_E] = TILE_WIND_E, [WIND_S] = TILE_WIND_S, [WIND_W] = TILE_WIND_W, [WIND_N] = TILE_WIND_N }; int tile_to_wind_[TILE__N] = { [TILE_WIND_E] = WIND_E, [TILE_WIND_S] = WIND_S, [TILE_WIND_W] = WIND_W, [TILE_WIND_N] = WIND_N }; int same_suit(TILE a, TILE b) { #define TILES(suit) \ TILE_1_##suit: case TILE_2_##suit: case TILE_3_##suit: case\ TILE_4_##suit: case TILE_5_##suit: case TILE_6_##suit: case\ TILE_7_##suit: case TILE_8_##suit: case TILE_9_##suit switch (a) { case TILES(BAMBOO): switch (b) { case TILES(BAMBOO): return(1); break; } break; case TILES(CHARACTER): switch (b) { case TILES(CHARACTER): return(1); break; } break; case TILES(DOT): switch (b) { case TILES(DOT): return(1); break; } break; } return(0); #undef TILES }