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