summaryrefslogtreecommitdiffstats
path: root/include/chess.h
blob: e1a50777d5d84db2b21eb01e12825ccc987794ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/* $Id$ */

#ifndef INCLUDE_CHESS_H
#define INCLUDE_CHESS_H

#define CHESS_DRAWING_TIME_ROW   128
#define CHESS_DRAWING_TURN_ROW   129
#define CHESS_DRAWING_WARN_ROW   130
#define CHESS_DRAWING_STEP_ROW   131
#define CHESS_DRAWING_HELP_ROW   132

#define CHESS_PHOTO_LINE      15
#define CHESS_PHOTO_COLUMN    (256 + 25)

struct ChessBroadcastList;
struct ChessActions;
struct ChessConstants;

#define const
#define static
#define private

typedef struct {
    char    userid[IDLEN + 1];
    int     win;
    int     lose;
    int     tie;
    unsigned short rating;
    unsigned short orig_rating; // 原始 rating, 因為遊戲開始先算輸一場, rating 值就跑掉了
} ChessUser;

private typedef struct {
    int   used;
    int   size;
    void *body;
} ChessHistory;

/*   棋類觀戰
 *
 * 雙人對戰時,雙方都會有一個 broadcast_list 的 linked-list,紀錄著每下一
 * 步棋,必須將這個訊息丟給那些人(sock)。
 * 每當一個觀棋者加入(觀棋可以從紅方或黑方的觀點進行),其中一方的下棋者
 * 的 broadcast_list 就會多一筆記錄,之後就會將下的或收到對方下的每一步棋
 * 傳給 broadcast_list 中所有需要的人,達到觀棋的效果。
 */
private typedef struct ChessBroadcastListNode {
    int    sock;
    struct ChessBroadcastListNode *next;
} ChessBroadcastListNode;

private typedef struct ChessBroadcastList {
    struct ChessBroadcastListNode head; /* dummy node */
} ChessBroadcastList;


typedef struct {
    int     limit_hand;
    int     limit_time;
    int     free_time;
    enum {
    CHESS_TIMEMODE_MULTIHAND, /* 限時限步 */
    CHESS_TIMEMODE_COUNTING   /* 讀秒 */
    } time_mode;
} ChessTimeLimit;

typedef enum {
    CHESS_MODE_VERSUS,   /* 對奕 */
    CHESS_MODE_WATCH,    /* 觀棋 */
    CHESS_MODE_PERSONAL, /* 打譜 */
    CHESS_MODE_REPLAY    /* 看譜 */
} ChessGameMode;

typedef enum {
    CHESS_RESULT_CONTINUE,
    CHESS_RESULT_WIN,
    CHESS_RESULT_LOST,
    CHESS_RESULT_TIE,
    CHESS_RESULT_END   /* watching or replaying */
} ChessGameResult;

typedef struct ChessInfo {
    private const static
    struct ChessActions* actions; /* vtable */
    private const static
    struct ChessConstants* constants;

    rc_t cursor;

    /* 計時用, [0] = mine, [1] = his */
    int     lefttime[2];
    int     lefthand[2]; /* 限時限步時用, = 0 表為自由時間或非限時限步模式 */
    const ChessTimeLimit* timelimit;

    const ChessGameMode mode;
    const ChessUser user1;
    const ChessUser user2;
    const char myturn;   /* 我方顏色 */

    char       turn;
    char       pass[2];
    char       warnmsg[64];
    char       last_movestr[36];
    char      *photo;

    void      *board;
    void      *tag;

    private int    sock;
    private ChessHistory history;
    private ChessBroadcastList broadcast_list;
    private ChessGameResult (*play_func[2])(struct ChessInfo* info);

    private int  current_step;  /* used by watch and replay */
    private char step_tmp[0];
} ChessInfo;

#undef const
#undef static
#undef private

typedef struct ChessActions {
    /* initial */
    void (*init_user)   (const userinfo_t* uinfo, ChessUser* user);
    void (*init_user_rec)(const userec_t* uinfo, ChessUser* user);
    void (*init_board)  (void* board);

    /* playing */
    void (*drawline)    (const ChessInfo* info, int line);
    void (*movecur)     (int r, int c);
    int  (*prepare_play)(ChessInfo* info);
    int  (*process_key) (ChessInfo* info, int key, ChessGameResult* result);
    int  (*select)      (ChessInfo* info, rc_t location,
        ChessGameResult* result);
    void (*prepare_step)(ChessInfo* info, const void* step);
    ChessGameResult (*apply_step)(void* board, const void* step);
    void (*drawstep)    (ChessInfo* info, const void* step);
    ChessGameResult (*post_game)(ChessInfo* info);

    /* ending */
    void (*gameend)    (ChessInfo* info, ChessGameResult result);
    void (*genlog)     (ChessInfo* info, FILE* fp, ChessGameResult result);
} ChessActions;

typedef struct ChessConstants {
    int   step_entry_size;
    int   traditional_timeout;
    int   board_height;
    int   board_width;
    int   pass_is_step;
    const char *chess_name;
    const char *photo_file_name;
    const char *log_board;
    const char *turn_color[2];
    const char *turn_str[2];
} ChessConstants;

typedef enum {
    CHESS_STEP_NORMAL, CHESS_STEP_PASS,
    CHESS_STEP_DROP, CHESS_STEP_FAILURE,
    CHESS_STEP_SPECIAL, /* chesses' special steps */
    CHESS_STEP_NOP,     /* for wake up */

    CHESS_STEP_TIE,  /* tie request */
    CHESS_STEP_TIE_ACC,  /* accept */
    CHESS_STEP_TIE_REJ,  /* reject */

    CHESS_STEP_UNDO, /* undo request */
    CHESS_STEP_UNDO_ACC,  /* accept */
    CHESS_STEP_UNDO_REJ,  /* reject */
} ChessStepType;


int ChessTimeCountDown(ChessInfo* info, int who, int length);
void ChessStepMade(ChessInfo* info, int who);

ChessStepType ChessStepReceive(ChessInfo* info, void* step); /* should this be public? */
int ChessStepSend(ChessInfo* info, const void* step);
int ChessMessageSend(ChessInfo* info, ChessStepType type);

void ChessHistoryAppend(ChessInfo* info, void* step);
const void* ChessHistoryRetrieve(ChessInfo* info, int n);

void ChessPlay(ChessInfo* info);
int ChessStartGame(char func_char, int sig, const char* title);
int ChessWatchGame(void (*play)(int, ChessGameMode),
    int game, const char* title);
int ChessReplayGame(const char* fname);

ChessInfo* NewChessInfo(const ChessActions* actions,
    const ChessConstants* constants, int sock, ChessGameMode mode);
void DeleteChessInfo(ChessInfo* info);

void ChessEstablishRequest(int sock);
void ChessAcceptingRequest(int sock);
void ChessShowRequest(void);

void ChessRedraw(const ChessInfo* info);
void ChessDrawLine(const ChessInfo* info, int line);
void ChessDrawExtraInfo(const ChessInfo* info, int line, int space);

#endif /* INCLUDE_CHESS_H */