📄 client.c
字号:
/* $Header: /home/jcb/newmj/RCS/client.c,v 11.3 2003/03/23 18:02:01 jcb Rel $ * client.c * Provides generic client support. It connects to the controller, * and maintains a game data structure in response to the Controller * messages. After updating the game structure, it (will) invokes a callback * installed by its user. *//****************** COPYRIGHT STATEMENT ********************** * This file is Copyright (c) 2000 by J. C. Bradfield. * * Distribution and use is governed by the LICENCE file that * * accompanies this file. * * The moral rights of the author are asserted. * * * ***************** DISCLAIMER OF WARRANTY ******************** * This code is not warranted fit for any purpose. See the * * LICENCE file for further information. * * * *************************************************************/static const char rcs_id[] = "$Header: /home/jcb/newmj/RCS/client.c,v 11.3 2003/03/23 18:02:01 jcb Rel $";#include "sysdep.h"#include <assert.h>#include "client.h"/* client_init: establish a connection to a controller */Game *client_init(char *address) { int fd; int i; Game *g; if ( strcmp("-",address) == 0 ) { fd = STDOUT_FILENO; } else { fd = connect_to_host(address); if ( fd == INVALID_SOCKET ) { perror("client_init: connect_to_host failed"); return 0; } } /* alloc the structures */ g = (Game *) malloc(sizeof(Game)); if ( g == NULL ) { warn("Couldn't malloc game structure"); exit(1); } memset((void *)g,0,sizeof(Game)); for ( i=0 ; i < NUM_SEATS ; i++ ) { if ( (g->players[i] = (PlayerP) malloc(sizeof(Player))) == NULL ) { warn("couldn't malloc player structure"); exit(1); } memset((void *)g->players[i],0,sizeof(Player)); } g->fd = fd; g->cseqno = 0; return g;}/* client_connect: take an id and a name, and send a connect message. Return 1 on success, or 0 on failure. */int client_connect(Game *g, int id, char *name) { PMsgConnectMsg cm; cm.type = PMsgConnect; cm.pvers = PROTOCOL_VERSION; cm.last_id = id; cm.name = name; client_send_packet(g,(PMsgMsg *)&cm); /* stash info in our own player record */ assert(g->players[0]); initialize_player(g->players[0]); set_player_id(g->players[0],id); set_player_name(g->players[0],name); return 1;}/* close connection and free storage */Game *client_close(Game *g) { int i; close_socket(g->fd); for ( i = 0; i < NUM_SEATS; i++ ) { set_player_name(g->players[i],NULL); free((void *)(g->players[i])); } free(g); g->fd = INVALID_SOCKET; return NULL;}/* client_send_packet: send the given packet out on the game fd. Return sequence number of packet. */int client_send_packet(Game *g, PMsgMsg *m) { char *l; if ( ! g ) { warn("client_send_packet: null game"); return 0; } l = encode_pmsg(m); if ( l == NULL ) { /* this shouldn't happen */ warn("client_send_packet: protocol conversion failed"); return 0; } if ( put_line(g->fd,l) < 0 ) { warn("client_send_packet: write failed"); /* maybe we should shutdown the descriptor here? */ return 0; } return ++g->cseqno;}/* see client.h for spec. */TileSet *client_find_sets(PlayerP p, Tile d, int mj, PlayerP *pcopies, MJSpecialHandFlags flags) { static TileSet ts[14]; /* should be safe, but FIXME */ static Player copies[14]; TileSet *tsp = ts; Tile t; PlayerP cp = copies; char seen[MaxTile]; /* to note tile denominations already done */ int j; /* check the discard */ if ( d != HiddenTile ) { /* Can we kong? */ if ( !mj && player_can_kong(p,d) ) { tsp->type = Kong; tsp->tile = d; tsp++; cp++; } /* Can we pung it? */ copy_player(cp,p); if ( player_pungs(cp,d) && (!mj || player_can_mah_jong(cp,HiddenTile,flags)) ) { tsp->type = Pung; tsp->tile = d; tsp++; cp++; } /* Can we chow it? */ for ( j = Lower; j <= Upper; j++ ) { copy_player(cp,p); if ( player_chows(cp,d,j) && (!mj || player_can_mah_jong(cp,HiddenTile,flags))) { tsp->type = Chow; tsp->tile = make_tile(suit_of(d),value_of(d)-j); tsp++; cp++; } } /* Can we pair it? */ copy_player(cp,p); if ( player_pairs(cp,d) && (!mj || player_can_mah_jong(cp,HiddenTile,flags)) ) { tsp->type = Pair; tsp->tile = d; tsp++; cp++; } } else { /* no discard. Look for closed sets */ /* Because we should return pungs, then chows, then pairs, we have to go through the tiles three times, which is tedious. */ for (j=0; j < MaxTile; j++) seen[j] = 0; for (j=0; j < p->num_concealed; j++) { t = p->concealed[j]; if ( seen[t]++ ) continue; /* don't enter sets twice */ copy_player(cp,p); if ( player_forms_closed_pung(cp,t) && (!mj || player_can_mah_jong(cp,HiddenTile,flags))) { tsp->type = ClosedPung; tsp->tile = t; tsp++; cp++; } } for (j=0; j < MaxTile; j++) seen[j] = 0; for (j=0; j < p->num_concealed; j++) { t = p->concealed[j]; if ( seen[t]++ ) continue; /* don't enter sets twice */ copy_player(cp,p); if ( player_forms_closed_chow(cp,t,Lower) && (!mj || player_can_mah_jong(cp,HiddenTile,flags))) { tsp->type = ClosedChow; tsp->tile = t; tsp++; cp++; } } for (j=0; j < MaxTile; j++) seen[j] = 0; for (j=0; j < p->num_concealed; j++) { t = p->concealed[j]; if ( seen[t]++ ) continue; /* don't enter sets twice */ copy_player(cp,p); if ( player_forms_closed_pair(cp,t) && (!mj || player_can_mah_jong(cp,HiddenTile,flags))) { tsp->type = ClosedPair; tsp->tile = t; tsp++; cp++; } } } /* have we found anything? */ if ( tsp == ts ) return (TileSet *)0; tsp->type = Empty; if ( pcopies ) *pcopies = copies; return ts;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -