⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gui.c

📁 一个网络和单机的麻将游戏源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    return len;  else     return -1;}/* a glib level wrapper for the server input callback */static gboolean gcallback(GIOChannel   *source UNUSED,			     GIOCondition  condition UNUSED,			    gpointer      data UNUSED) {  server_input_callback(NULL,0,GDK_INPUT_READ);  return 1;}#endif /* WIN32 */intmain (int argc, char *argv[]){  int do_connect = 0;  int i;    /* install the warning hook for gui users */  log_msg_hook = log_msg_add;  /* we have to set up the default preferences table before     reading the rcfile */  game_copy_option_table(&prefs_table,&game_default_optiontable);  /* read rc file. We should have an option to suppress this */  read_rcfile(NULL);  showwall = pref_showwall;  /* options. I should use getopt ... */  for (i=1;i<argc;i++) {    if ( strcmp(argv[i],"--id") == 0 ) {      if ( ++i == argc ) usage(argv[0],"missing argument to --id");      our_id = atoi(argv[i]);    } else if ( strcmp(argv[i],"--server") == 0 ) {      if ( ++i == argc ) usage(argv[0],"missing argument to --server");      strncpy(address,argv[i],255);    } else if ( strcmp(argv[i],"--name") == 0 ) {      if ( ++i == argc ) usage(argv[0],"missing argument to --name");      strncpy(name,argv[i],255);    } else if ( strcmp(argv[i],"--connect") == 0 ) {      do_connect = 1;    } else if ( strcmp(argv[i],"--show-wall") == 0 ) {      pref_showwall = showwall = 1;    } else if ( strcmp(argv[i],"--no-show-wall") == 0 ) {      pref_showwall = showwall = 0;    } else if ( strcmp(argv[i],"--size") == 0 ) {      if ( ++i == argc ) usage(argv[0],"missing argument to --size");      display_size = atoi(argv[i]);    } else if ( strcmp(argv[i],"--animate") == 0 ) {      animate = 1;    } else if ( strcmp(argv[i],"--tileset") == 0 ) {      if ( ++i == argc ) usage(argv[0],"missing argument to --tileset");      tileset = argv[i];    } else if ( strcmp(argv[i],"--tileset-path") == 0 ) {      if ( ++i == argc ) usage(argv[0],"missing argument to --tileset-path");      tileset_path = argv[i];    } else if ( strcmp(argv[i],"--echo-server") == 0 ) {      debug = 1;    } else if ( strcmp(argv[i],"--dialogs-popup") == 0 ) {      dialogs_position = DialogsPopup;    } else if ( strcmp(argv[i],"--dialogs-below") == 0 ) {      dialogs_position = DialogsBelow;    } else if ( strcmp(argv[i],"--dialogs-central") == 0 ) {      dialogs_position = DialogsCentral;    } else if ( strcmp(argv[i],"--pass-stdin") == 0 ) {      pass_stdin = 1;    } else {      usage(argv[0],"unknown option or argument");      exit(1);    }  }  gtk_init (&argc, &argv);  #ifdef WIN32  initialize_sockets(skt_open_transform,skt_closer,		     skt_reader,skt_writer);#endif  /* stash the unmodified default style, so we know what the     default font is */  original_default_style = gtk_style_copy(gtk_widget_get_default_style());  /* Now we've done basic setup, create all the windows.     This also involves reading tile pixmaps etc */  /* These two signals are bound to left and right arrow accelerators     in order to move the tile selection left or right */  gtk_object_class_user_signal_new(    GTK_OBJECT_CLASS(gtk_type_class(GTK_TYPE_WIDGET)),       "selectleft", GTK_RUN_FIRST, gtk_signal_default_marshaller, GTK_TYPE_NONE,0);  gtk_object_class_user_signal_new(    GTK_OBJECT_CLASS(gtk_type_class(GTK_TYPE_WIDGET)),       "selectright", GTK_RUN_FIRST, gtk_signal_default_marshaller, GTK_TYPE_NONE,0);  create_display();#if 0  /* not wanted at present, but left here so we remember how to do it */  /* we create a new popup signal which we will send to dialogs when     they're popped up and we want them to set focus to the appropriate     button */  gtk_object_class_user_signal_new(GTK_OBJECT_CLASS(gtk_type_class(gtk_type_from_name("GtkWidget"))), "popup", GTK_RUN_FIRST, gtk_signal_default_marshaller, GTK_TYPE_NONE,0);#endif  /* and the open dialog */  {    char idt[10];    idt[0] = 0;    sprintf(idt,"%d",our_id);    open_dialog_init(idt,name);  }  /* now check the dialog state */  setup_dialogs();  if ( do_connect ) open_connection(0,0);  /* initialize time stamps */  gettimeofday(&start_tv,NULL);  gtk_main ();    return 0;}static int querykong = 0; /* used during kong robbing query */static void server_input_callback(gpointer data UNUSED,                            gint              sourceparam UNUSED, 			   GdkInputCondition conditionparam UNUSED) {  char *l;  CMsgUnion *m;  int id;  int i;  l = get_line(the_game->fd);  if ( debug ) fputs(l ? l : "NULL LINE\n",stdout);  if ( ! l ) {    fprintf(stderr,"receive error from controller\n");    error_dialog_popup("Lost connection to server");    close_connection();    return;  }  m = (CMsgUnion *)decode_cmsg(l);  if ( ! m ) {    fprintf(stderr,"protocol error from controller\n");    return;  }  if ( m->type == CMsgConnectReply ) {    our_id = ((CMsgConnectReplyMsg *)m)->id;    /* need to set this again if this is a second connectreply       in response to loadstate */    our_player = the_game->players[0];    if ( our_id == 0 ) {      char s[1024];      close_connection();      strcpy(s,"Server refused connection because: ");      strcat(s,((CMsgConnectReplyMsg *)m)->reason);      error_dialog_popup(s);      return;    } else {      PMsgSetPlayerOptionMsg spom;      /* stash the server's protocol version */      server_pversion = m->connectreply.pvers;      /* set our name again, in case we got deleted! */      set_player_name(our_player,name);      /* since we have a human driving us, ask the controller to slow down	 a bit; especially if we're animating */      spom.type = PMsgSetPlayerOption;      spom.option = PODelayTime;      spom.ack = 0;      spom.value = animate ? 10 : 5; /* 0.5 or 1 second min delay */      spom.text = NULL;      send_packet(&spom);      /* if the controller is likely to understand it,	 request that we may handle timeouts locally */      if ( m->connectreply.pvers >= 1036 ) {	spom.option = POLocalTimeouts;	spom.value = 1;	send_packet(&spom);      }    }  }  /* skip InfoTiles */  if ( m->type == CMsgInfoTiles ) return;  /* error messages */  if ( m->type == CMsgError ) {    error_dialog_popup(m->error.error);    /* better set up dialogs here */    setup_dialogs();    return;  }      /* player options */  if ( m->type == CMsgPlayerOptionSet ) {    /* the only player option that is significant for us       is LocalTimeouts */    if ( m->playeroptionset.option == POLocalTimeouts ) {      local_timeouts = m->playeroptionset.value;      if ( ! m->playeroptionset.ack ) {	/* this was a command from the server -- acknowledge it */	PMsgSetPlayerOptionMsg spom;	spom.type = PMsgSetPlayerOption;	spom.option = POLocalTimeouts;	spom.value = local_timeouts;	spom.text = NULL;	spom.ack = 1;	send_packet(&spom);      }    }    /* any other option we just ignore, since we have no corresponding       state */    return;  }  id = game_handle_cmsg(the_game,(CMsgMsg *)m);  calling = 0; /* awful global flag to detect calling */  /* This is the place where we take intelligent action in     response to the game. As a matter of principle, we don't do this,      but there is an exception: if there is a kong to be robbed,     we will check to see whether we can actually go out with the tile,     and if we can't, we'll send in NoClaim directly, rather than     asking the user */  /* We can't assume that we know whether we can go mahjong.     The server might allow special winning hands that we don't know     about. So we have to ask the server whether we can go MJ.  */  /* we might get the kong message as part of the replay. So we have     to respond the first time we get a message after a kong and     the game is active */  if ( the_game->active && id != our_id && ! querykong       && (the_game->state == Discarding 	   || the_game->state == DeclaringSpecials)       && the_game->konging        && the_game->claims[our_seat] == UnknownClaim ) {    PMsgQueryMahJongMsg qmjm;    qmjm.type = PMsgQueryMahJong;    qmjm.tile = the_game->tile;    send_packet(&qmjm);    querykong = 1;  }  /* and if this is the reply, send no claim if appropriate */  if ( the_game->active && (the_game->state == Discarding 	   || the_game->state == DeclaringSpecials)       && the_game->konging        && m->type == CMsgCanMahJong       && ! m->canmahjong.answer) {    disc_callback(NULL,(gpointer) NoClaim); /* sends the message */    the_game->claims[our_seat] = NoClaim; /* hack to stop the window coming up */  }  if ( m->type == CMsgCanMahJong ) querykong = 0;  status_update(m->type == CMsgGameOver);  if ( id == our_id ) player_sort_tiles(our_player);  /* some more "intelligent action" comes now */  /* if we should be auto-declaring specials, deal with it */  if ( playing_auto_declare_specials ) {    if ( m->type == CMsgPlayerDeclaresSpecial       && id == our_id ) {      auto_declaring_special = 0;      may_declare_kong = 0;    }    if ( the_game->active      && ! the_game->paused      && ( the_game->state == DeclaringSpecials	|| the_game->state == Discarding )      && the_game->needs == FromNone      && the_game->player == our_seat      && !auto_declaring_special ) {      PMsgDeclareSpecialMsg pdsm;      Tile t;      pdsm.type = PMsgDeclareSpecial;      /* if we have a special, declare it. We've sorted our	 tiles, so we know the specials are at the right */      /* if we're declaring specials, but have none, send the finished	 message */      assert(our_player->num_concealed > 0);      t = our_player->concealed[our_player->num_concealed-1];      if ( is_special(t) ) {	pdsm.tile = t;	send_packet(&pdsm);	auto_declaring_special = 1;      } else if ( the_game->state == DeclaringSpecials ) {	/* First, we have to check whether we have a kong in hand,	   since then the human must have the option to declare it */	int i;	for ( i = 0; i < our_player->num_concealed; i++ ) {	  if ( player_can_declare_closed_kong(our_player,		 our_player->concealed[i]) ) {	    may_declare_kong = 1;	    break;	  }	}	if ( ! may_declare_kong ) {	  pdsm.tile = HiddenTile;	  send_packet(&pdsm);	  auto_declaring_special = 1;	} else {	  /* select the kong we found */	  selected_button = i;	  conc_callback(pdisps[0].conc[i],(gpointer)(i | 128));	}      }    }  }  /* if we should be auto-declaring hands, deal with it */  if ( playing_auto_declare_losing || playing_auto_declare_winning ) {    /* this is mind-numbingly tedious. There has to be a better way. */    if ( (m->type == CMsgPlayerPungs	   || m->type == CMsgPlayerFormsClosedPung	   || m->type == CMsgPlayerKongs	   || m->type == CMsgPlayerDeclaresClosedKong	   || m->type == CMsgPlayerChows	   || m->type == CMsgPlayerFormsClosedChow	   || m->type == CMsgPlayerPairs	   || m->type == CMsgPlayerFormsClosedPair	   || m->type == CMsgPlayerSpecialSet	   || m->type == CMsgPlayerFormsClosedSpecialSet )      && id == our_id ) auto_declaring_hand = 0;    /* and to make sure it does get cleared */    if ( pflag(our_player,HandDeclared) ) auto_declaring_hand = 0;    if ( !auto_declaring_hand      && the_game->active      && ! the_game->paused      && ( the_game->state == MahJonging )      && !(the_game->mjpending && the_game->player != our_seat)      && !pflag(our_player,HandDeclared)       && ((the_game->player == our_seat && playing_auto_declare_winning)	   || (pflag(the_game->players[the_game->player],HandDeclared) 	       && playing_auto_declare_losing) ) ) {      TileSet *tsp;      MJSpecialHandFlags mjspecflags;      PMsgUnion m;      mjspecflags = 0;      if ( game_get_option_value(the_game,GOSevenPairs,NULL) )	mjspecflags |= MJSevenPairs;      /* OK, let's find a concealed set to declare */      auto_declaring_hand = 1;      /* following code nicked from greedy.c */      /* get the list of possible decls */      tsp = client_find_sets(our_player,	(the_game->player == our_seat	  && the_game->mjpending)	? the_game->tile : HiddenTile,	the_game->player == our_seat,	(PlayerP *)0,mjspecflags);      if ( !tsp && our_player->num_concealed > 0 ) {	/* Can't find a set to declare, and still have concealed	   tiles left. Either we're a loser, or we have Thirteen	   Orphans (or some other special hand). */	if ( the_game->player == our_seat ) {	  if ( the_game->mjpending ) {	    m.type = PMsgSpecialSet;	  } else {	    m.type = PMsgFormClosedSpecialSet;	  }	} else {	  m.type = PMsgShowTiles;	}	send_packet(&m);      } else {	/* just do the first one */	switch ( tsp->type ) {	case Kong:	  /* we can't declare a kong now, so declare the pung instead */	case Pung:	  m.type = PMsgPung;	  m.pung.discard = 0;	  break;	case Chow:	  m.type = PMsgChow;	  m.chow.discard = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -