1 /*
2 * src/client/look.c, part of Complete Goban (game program)
3 * Copyright (C) 1996 William Shubert
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <wms.h>
8 #include <but/but.h>
9 #include <but/text.h>
10 #include <but/ctext.h>
11 #ifndef _MSG_H_
12 #include "../msg.h"
13 #endif
14 #ifdef _CLIENT_LOOK_H_
15 LEVELIZATION ERROR
16 #endif
17 #include "look.h"
18
19
20 /**********************************************************************
21 * Forward Declarations
22 **********************************************************************/
23 static void gameReady(CliLook *look, int size);
24 static GobanOut quit(void *packet);
25 static void gobanDead(void *packet);
26 static bool moveOk(void *packet);
27 static void makeMoves(GoGame *game, const char *board, int size);
28
29
30 /**********************************************************************
31 * Functions
32 **********************************************************************/
cliLook_init(CliLook * look,Cgoban * cg,CliServer server)33 void cliLook_init(CliLook *look, Cgoban *cg, CliServer server) {
34 GoStone s;
35
36 MAGIC_SET(look);
37 look->cg = cg;
38 look->server = server;
39 look->state = cliLook_ready;
40 goStoneIter(s) {
41 str_init(&look->name[s]);
42 str_init(&look->rank[s]);
43 }
44 str_init(&look->boardData);
45 }
46
47
cliLook_deinit(CliLook * look)48 void cliLook_deinit(CliLook *look) {
49 GoStone s;
50
51 assert(MAGIC(look));
52 goStoneIter(s) {
53 str_deinit(&look->name[s]);
54 str_deinit(&look->rank[s]);
55 }
56 str_deinit(&look->boardData);
57 MAGIC_UNSET(look);
58 }
59
60
cliLook_gotData(CliLook * look,const char * buf)61 void cliLook_gotData(CliLook *look, const char *buf) {
62 GoStone s;
63 int lineNum, matches;
64 char data[GOBOARD_MAXSIZE + 1];
65 char name[40], rank[10];
66
67 assert(MAGIC(look));
68 switch(look->state) {
69 case cliLook_ready:
70 look->skip = FALSE;
71 str_clip(&look->boardData, 0);
72 /* Fall through to cliLook_info1. */
73 case cliLook_info:
74 s = (look->state - cliLook_ready) + goStone_white;
75 matches = sscanf(buf, "%39s %9s %d %*d %*d %*s %g %d",
76 name, rank, &look->captures[s],
77 &look->komi, &look->handicap);
78 assert(matches == 5);
79 str_copyChars(&look->name[s], name);
80 str_copyChars(&look->rank[s], rank);
81 ++look->state;
82 break;
83 case cliLook_body:
84 matches = sscanf(buf, "%d: %s", &lineNum, data);
85 assert(matches == 2);
86 assert(strlen(data) <= GOBOARD_MAXSIZE);
87 str_catChars(&look->boardData, data);
88 if (lineNum == strlen(data) - 1) {
89 gameReady(look, lineNum + 1);
90 look->state = cliLook_ready;
91 }
92 break;
93 }
94 }
95
96
gameReady(CliLook * look,int size)97 static void gameReady(CliLook *look, int size) {
98 static const GobanActions actions = {
99 NULL, quit, NULL,
100 NULL, NULL, NULL, NULL,
101 NULL, NULL, NULL,
102 NULL, NULL, /* edit, gameInfo */
103 &help_cliLook, gobanDead,
104 moveOk, moveOk, moveOk, moveOk};
105 Goban *goban;
106 GoGame *game;
107 Str title;
108 static const GoTime noTime = {goTime_none, 0, 0, 0};
109 CliLookChild *child;
110 int i;
111
112 /*
113 * If it's a game-end board, then don't show it.
114 * You can tell these because they have 3s, 4s, and 5s in them.
115 */
116 for (i = 0; i < str_len(&look->boardData); ++i) {
117 assert(str_chars(&look->boardData)[i] >= '0');
118 assert(str_chars(&look->boardData)[i] <= '6');
119 if ((str_chars(&look->boardData)[i] > '2') &&
120 (str_chars(&look->boardData)[i] < '6')) {
121 return;
122 }
123 }
124 child = wms_malloc(sizeof(CliLookChild));
125 MAGIC_SET(child);
126 str_init(&title);
127 str_print(&title, msg_cliLookName,
128 str_chars(&look->name[goStone_white]),
129 str_chars(&look->rank[goStone_white]),
130 str_chars(&look->name[goStone_black]),
131 str_chars(&look->rank[goStone_black]));
132 /*
133 * I pass in a handicap of 0 even though I know the real handicap. Why?
134 * because otherwise when I parse over the board, if I find a white
135 * stone where there used to be a handicap stone, I'm screwed! I'd have
136 * to erase the black stone somehow and add a white one. Ugh. Easier
137 * just to never add the handicap stones to begin with; they'll be caught
138 * when I scan the board later.
139 */
140 game = goGame_create(size, goRules_japanese, 0, look->komi,
141 &noTime, TRUE);
142 makeMoves(game, str_chars(&look->boardData), size);
143 goban = goban_create(look->cg, &actions, child, game, "client.look",
144 str_chars(&title));
145 goban->pic->allowedMoves = goPicMove_noWhite | goPicMove_noBlack;
146 goban->iDec1 = grid_create(&look->cg->cgbuts, NULL, NULL,
147 goban->iWin, 2, BUT_DRAWABLE, 0);
148 grid_setStone(goban->iDec1, goStone_white, FALSE);
149 if (look->server == cliServer_nngs)
150 grid_setVersion(goban->iDec1, CGBUTS_WORLDWEST(0));
151 else
152 grid_setVersion(goban->iDec1, CGBUTS_WORLDEAST(0));
153 goban_update(goban);
154 butText_set(goban->infoText, "Static Game Board");
155 child->game = game;
156 child->goban = goban;
157 str_deinit(&title);
158 }
159
160
quit(void * packet)161 static GobanOut quit(void *packet) {
162 CliLookChild *child = packet;
163
164 assert(MAGIC(child));
165 goban_destroy(child->goban, TRUE);
166 return(gobanOut_noDraw);
167 }
168
169
gobanDead(void * packet)170 static void gobanDead(void *packet) {
171 CliLookChild *child = packet;
172
173 assert(MAGIC(child));
174 goGame_destroy(child->game);
175 MAGIC_UNSET(child);
176 wms_free(child);
177 }
178
179
moveOk(void * packet)180 static bool moveOk(void *packet) {
181 return(FALSE);
182 }
183
184
makeMoves(GoGame * game,const char * board,int size)185 static void makeMoves(GoGame *game, const char *board, int size) {
186 int x, y;
187
188 for (x = 0; x < size; ++x) {
189 for (y = 0; y < size; ++y) {
190 switch(*board) {
191 case '0':
192 goGame_move(game, goStone_black,
193 goBoard_xy2Loc(game->board, x, y), NULL);
194 break;
195 case '1':
196 goGame_move(game, goStone_white,
197 goBoard_xy2Loc(game->board, x, y), NULL);
198 break;
199 case '2':
200 case '6':
201 break;
202 default:
203 assert(0);
204 break;
205 }
206 ++board;
207 }
208 }
209 goGame_pass(game, goStone_black, NULL); /* These passes just get rid of */
210 goGame_pass(game, goStone_white, NULL); /* the "last move here" marker. */
211 }
212