Exemplo n.º 1
0
cstring *ser_wallet(const struct wallet *wlt)
{
	struct bp_key *key;

	cstring *rs = cstr_new_sz(20 * 1024);

	/*
	 * ser "root" record
	 */
	{
	cstring *s_root = ser_wallet_root(wlt);
	cstring *recdata = message_str(wlt->chain->netmagic,
				       "root", s_root->str, s_root->len);
	cstr_append_buf(rs, recdata->str, recdata->len);
	cstr_free(recdata, true);
	cstr_free(s_root, true);
	}

	/* ser "privkey" records */
	wallet_for_each_key(wlt, key) {
		void *privkey = NULL;
		size_t pk_len = 0;

		bp_privkey_get(key, &privkey, &pk_len);

		cstring *recdata = message_str(wlt->chain->netmagic,
					       "privkey",
					       privkey, pk_len);
		free(privkey);

		cstr_append_buf(rs, recdata->str, recdata->len);
		cstr_free(recdata, true);
	}
Exemplo n.º 2
0
QSharedPointer<MsgBase> LinkLayerIcarus::getNextMessage()
{
    QSharedPointer<MsgBase> message;
    int index_start = 0;

    // The token ":" must be the second in a message, so if the colon
    // appears at first position, the message type may be lost
    while((index_start = this->buffer->indexOf(":"), index_start)<1)
    {
        if(index_start == -1) // Not found
        {
            return message; //Empty
        }
    }

    // Now, we search for the end of the message. If the method indexOf
    // returns -1, the buffer has no token ";", so the message is incomplete
    int index_end = this->buffer->indexOf(";", index_start);
    if(index_end == -1) // Not found
    {
        return message; //Empty
    }

    // If we found a message in the buffer, we extract it and pop it from the buffer
    QString message_str(this->buffer->mid(index_start -1, index_end - index_start + 1));
    this->buffer->remove(0, index_end);

    message = QSharedPointer<MsgBase>(new MsgBase(message_str));
    return message;
}
Exemplo n.º 3
0
Arquivo: cmd4.c Projeto: jcubic/ToME
/*
 * Recall the most recent message
 */
void do_cmd_message_one(void)
{
	cptr msg = format("> %s", message_str(0));

	/* Recall one message XXX XXX XXX */
	display_message(0, 0, strlen(msg), message_color(0), msg);
}
Exemplo n.º 4
0
static cstring *blkdb_ser_rec(struct blkdb *db, const struct blkinfo *bi)
{
	cstring *data = ser_blkinfo(bi);

	cstring *rs = message_str(db->netmagic, "rec", data->str, data->len);

	cstr_free(data, true);

	return rs;
}
Exemplo n.º 5
0
static bool ser_peerman(struct peer_manager *peers, int fd)
{
	/* write "magic number" (constant first file record) */
	GString *rec = message_str(chain->netmagic, "magic.peers", NULL, 0);
	unsigned int rec_len = rec->len;
	ssize_t wrc = write(fd, rec->str, rec_len);

	g_string_free(rec, TRUE);

	if (wrc != rec_len)
		return false;

	if (debugging)
		fprintf(stderr, "peerman: %u peers to write\n",
			g_list_length(peers->addrlist));

	/* write peer list */
	GList *tmp = peers->addrlist;
	while (tmp) {
		struct peer *peer;

		peer = tmp->data;
		tmp = tmp->next;

		GString *msg_data = g_string_sized_new(sizeof(struct peer));
		ser_peer(msg_data, CADDR_TIME_VERSION, peer);

		rec = message_str(chain->netmagic, "peer",
				  msg_data->str, msg_data->len);

		rec_len = rec->len;
		wrc = write(fd, rec->str, rec_len);

		g_string_free(rec, TRUE);
		g_string_free(msg_data, TRUE);

		if (wrc != rec_len)
			return false;
	}

	return true;
}
Exemplo n.º 6
0
static bool ser_peerman(struct peer_manager *peers, int fd,  const struct chain_info *chain)
{
	/* write "magic number" (constant first file record) */
	cstring *rec = message_str(chain->netmagic, "magic.peers", NULL, 0);
	unsigned int rec_len = rec->len;
	ssize_t wrc = write(fd, rec->str, rec_len);

	cstr_free(rec, true);

	if (wrc != rec_len)
		return false;

	log_debug("peerman: %zu peers to write",
		clist_length(peers->addrlist));

	/* write peer list */
	clist *tmp = peers->addrlist;
	while (tmp) {
		struct peer *peer;

		peer = tmp->data;
		tmp = tmp->next;

		cstring *msg_data = cstr_new_sz(sizeof(struct peer));
		ser_peer(msg_data, CADDR_TIME_VERSION, peer);

		rec = message_str(chain->netmagic, "peer",
				  msg_data->str, msg_data->len);

		rec_len = rec->len;
		wrc = write(fd, rec->str, rec_len);

		cstr_free(rec, true);
		cstr_free(msg_data, true);

		if (wrc != rec_len)
			return false;
	}

	return true;
}
Exemplo n.º 7
0
static bool nc_conn_send(struct nc_conn *conn, const char *command,
			 const void *data, size_t data_len)
{
	LOG("attempting to send:[%s] to %s", command, conn->addr_str);
	/* build wire message */
	cstring *msg = message_str(chain->netmagic, command, data, data_len);
	if (!msg)
		return false;

	/* buffer now owns message data */
	struct buffer *buf = calloc(1, sizeof(struct buffer));
	buf->p = msg->str;
	buf->len = msg->len;

	cstr_free(msg, false);

	/* if write q exists, write_evt will handle output */
	if (conn->write_q) {
		conn->write_q = clist_append(conn->write_q, buf);
		return true;
	}

	/* attempt optimistic write */
	ssize_t wrc = write(conn->fd, buf->p, buf->len);

	if (wrc < 0) {
		if (errno != EAGAIN && errno != EWOULDBLOCK) {
			free(buf->p);
			free(buf);
			return false;
		}

		conn->write_q = clist_append(conn->write_q, buf);
		goto out_wrstart;
	}

	/* message fully sent */
	if (wrc == buf->len) {
		free(buf->p);
		free(buf);
		return true;
	}

	/* message partially sent; pause read; poll for writable */
	conn->write_q = clist_append(conn->write_q, buf);
	conn->write_partial = wrc;

out_wrstart:
	nc_conn_read_disable(conn);
	nc_conn_write_enable(conn);
	return true;
}
Exemplo n.º 8
0
  void chordService::detectNodesResponse() {
    DEBUG_PRINT("chord service starts detect nodes response process.");
    struct sockaddr_in addr;
    int fd;
    socklen_t addrlen;
    struct ip_mreq mreq;
    char message[100];
    char prefix[20];
    std::string prefix_str;
    sprintf(prefix, "type:%d", chordMessager::chordMessageType::messageDetectNode);
    prefix_str = std::string(prefix);

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
      throw ERRORS::chordServiceSocketCreateFail();
    }
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(SERVICE_DETECT_PORT_BIND);
    addrlen = sizeof(addr);
    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
      throw ERRORS::chordServiceSocketBindFail();
    }
    mreq.imr_multiaddr.s_addr = inet_addr(GROUP_IP);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
      throw ERRORS::chordServiceSetSocketOptFail();
    }
    while (true) {
      ssize_t cnt = recvfrom(fd, message, sizeof(message), 0, (struct sockaddr*)&addr, &addrlen);
      if (cnt < 0) {
        throw ERRORS::chordServiceRecvfromFail();
      }else if (cnt > 0) {
        std::string message_str(message);
        if (message_str.find(prefix_str) == 0) {
          //this is a detectNode message
          //return this node info back to the source
          chordMessager::chordMessageBase* inmsg = nullptr;
          chordMessager::chordMessager::deserializeMessage(message_str, inmsg);
          chordMessager::chordMessageDetectNodeResponse* outmsg = new chordMessager::chordMessageDetectNodeResponse(serviceChordNode->thisNode, inmsg->getNodeParam()[0], serviceChordNode->thisNode);
          delete inmsg;
          inmsg = nullptr;
          serviceChordNode->makeRequest(outmsg, inmsg);
          delete inmsg;
        }
      }
      std::this_thread::sleep_for(std::chrono::seconds(5));
    }
  }
Exemplo n.º 9
0
void wr_messages(void)
{
	s16b i;
	u16b num;

	num = messages_num();
	if (num > 80) num = 80;
	wr_u16b(num);

	/* Dump the messages (oldest first!) */
	for (i = num - 1; i >= 0; i--)
	{
		wr_string(message_str(i));
		wr_u16b(message_type(i));
	}
}
Exemplo n.º 10
0
	wallet_for_each_mkey(wlt, hdkey) {

		struct hd_extended_key_serialized hdraw;
		bool rc = write_ek_ser_prv(&hdraw, hdkey);
		assert(rc == true);

		cstring *recdata = message_str(wlt->chain->netmagic,
					       "hdmaster",
					       hdraw.data,
					       sizeof(hdraw.data) - 1);

		assert(recdata != NULL);

		cstr_append_buf(rs, recdata->str, recdata->len);
		cstr_free(recdata, true);
	}
Exemplo n.º 11
0
Arquivo: xtra1.c Projeto: jcubic/ToME
/*
 * Hack -- display recent messages in sub-windows
 *
 * XXX XXX XXX Adjust for width and split messages
 */
void fix_message(void)
{
	s32b j, i;
	s32b w, h;
	s32b x, y;

	/* Scan windows */
	for (j = 0; j < 8; j++)
	{
		term *old = Term;

		/* No window */
		if (!angband_term[j]) continue;

		/* No relevant flags */
		if (!flag_exists(&window_flag[j], FLAG_PW_MESSAGE)) continue;

		/* Activate */
		Term_activate(angband_term[j]);

		/* Get size */
		Term_get_size(&w, &h);

		/* Dump messages */
		for (i = 0; i < h; i++)
		{
			/* Dump the message on the appropriate line */
			display_message(0, (h - 1) - i, strlen(message_str((s16b)i)), message_color((s16b)i), message_str((s16b)i));

			/* Cursor */
			Term_locate(&x, &y);

			/* Clear to end of line */
			Term_erase(x, y, 255);
		}

		/* Fresh */
		Term_fresh();

		/* Restore */
		Term_activate(old);
	}
}
Exemplo n.º 12
0
static void init_block0(void)
{
	const char *genesis_hex = NULL;

	switch (chain->chain_id) {
	case CHAIN_BITCOIN:
		genesis_hex = genesis_bitcoin;
		break;
	case CHAIN_TESTNET3:
		genesis_hex = genesis_testnet;
		break;
	default:
		fprintf(plog, "unsupported chain.  add genesis block here!\n");
		exit(1);
		break;
	}

	size_t olen = 0;
	size_t genesis_rawlen = strlen(genesis_hex) / 2;
	char genesis_raw[genesis_rawlen];
	if (!decode_hex(genesis_raw, sizeof(genesis_raw), genesis_hex, &olen)) {
		fprintf(plog, "chain hex decode fail\n");
		exit(1);
	}

	cstring *msg0 = message_str(chain->netmagic, "block",
				    genesis_raw, genesis_rawlen);
	ssize_t bwritten = write(blocks_fd, msg0->str, msg0->len);
	if (bwritten != msg0->len) {
		fprintf(plog, "blocks write0 failed: %s\n", strerror(errno));
		exit(1);
	}
	cstr_free(msg0, true);

	off64_t fpos64 = lseek64(blocks_fd, 0, SEEK_SET);
	if (fpos64 == (off64_t)-1) {
		fprintf(plog, "blocks lseek0 failed: %s\n", strerror(errno));
		exit(1);
	}

	fprintf(plog, "blocks: genesis block written\n");
}
Exemplo n.º 13
0
void TSaslServerTransport::handleSaslStartMessage() {
  uint32_t resLength;
  NegotiationStatus status;

  uint8_t* message = receiveSaslMessage(&status, &resLength);
  // Message is a non-null terminated string; to use it like a
  // C-string we have to copy it into a null-terminated buffer.
  string message_str(reinterpret_cast<char*>(message), resLength);

  if (status != TSASL_START) {
    stringstream ss;
    ss << "Expecting START status, received " << status;
    sendSaslMessage(TSASL_ERROR,
                    reinterpret_cast<const uint8_t*>(ss.str().c_str()), ss.str().size());
    throw TTransportException(ss.str());
  }
  map<string, TSaslServerDefinition*>::iterator defn =
      TSaslServerTransport::serverDefinitionMap_.find(message_str);
  if (defn == TSaslServerTransport::serverDefinitionMap_.end()) {
    stringstream ss;
    ss << "Unsupported mechanism type " << message_str;
    sendSaslMessage(TSASL_BAD,
                    reinterpret_cast<const uint8_t*>(ss.str().c_str()), ss.str().size());
    throw TTransportException(TTransportException::BAD_ARGS, ss.str());
  }
  // TODO: when should realm be used?
  string realm;
  TSaslServerDefinition* serverDefinition = defn->second;
  sasl_.reset(new TSaslServer(serverDefinition->protocol_,
                              serverDefinition->serverName_, realm,
                              serverDefinition->flags_,
                              &serverDefinition->callbacks_[0]));
  // First argument is interpreted as C-string
  sasl_->evaluateChallengeOrResponse(
      reinterpret_cast<const uint8_t*>(message_str.c_str()), resLength, &resLength);

}
Exemplo n.º 14
0
/**
 * Write a character dump
 */
void write_character_dump(ang_file *fff)
{
	int i, x, y;

	int a;
	wchar_t c;

	struct store *home = &stores[STORE_HOME];
	struct object **home_list = mem_zalloc(sizeof(struct object *) *
										   z_info->store_inven_max);
	char o_name[80];

	char buf[1024];
	char *p;

	/* Begin dump */
	file_putf(fff, "  [%s Character Dump]\n\n", buildid);

	/* Display player */
	display_player(0);

	/* Dump part of the screen */
	for (y = 1; y < 23; y++) {
		p = buf;
		/* Dump each row */
		for (x = 0; x < 79; x++) {
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		file_putf(fff, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fff, "\n");

	/* Display player */
	display_player(1);

	/* Dump part of the screen */
	for (y = 11; y < 20; y++) {
		p = buf;
		/* Dump each row */
		for (x = 0; x < 39; x++) {
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		file_putf(fff, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fff, "\n");

	/* Dump part of the screen */
	for (y = 11; y < 20; y++) {
		p = buf;
		/* Dump each row */
		for (x = 0; x < 39; x++) {
			/* Get the attr/char */
			(void)(Term_what(x + 40, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		file_putf(fff, "%s\n", buf);
	}

	/* Skip some lines */
	file_putf(fff, "\n\n");


	/* If dead, dump last messages -- Prfnoff */
	if (player->is_dead) {
		i = messages_num();
		if (i > 15) i = 15;
		file_putf(fff, "  [Last Messages]\n\n");
		while (i-- > 0)
		{
			file_putf(fff, "> %s\n", message_str((s16b)i));
		}
		file_putf(fff, "\nKilled by %s.\n\n", player->died_from);
	}


	/* Dump the equipment */
	file_putf(fff, "  [Character Equipment]\n\n");
	for (i = 0; i < player->body.count; i++) {
		struct object *obj = slot_object(player, i);
		if (!obj) continue;

		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
		file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name);
		object_info_chardump(fff, obj, 5, 72);
	}
	file_putf(fff, "\n\n");

	/* Dump the inventory */
	file_putf(fff, "\n\n  [Character Inventory]\n\n");
	for (i = 0; i < z_info->pack_size; i++) {
		struct object *obj = player->upkeep->inven[i];
		if (!obj) break;

		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
		file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name);
		object_info_chardump(fff, obj, 5, 72);
	}
	file_putf(fff, "\n\n");

	/* Dump the quiver */
	file_putf(fff, "\n\n  [Character Quiver]\n\n");
	for (i = 0; i < z_info->quiver_size; i++) {
		struct object *obj = player->upkeep->quiver[i];
		if (!obj) continue;

		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
		file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name);
		object_info_chardump(fff, obj, 5, 72);
	}
	file_putf(fff, "\n\n");

	/* Dump the Home -- if anything there */
	store_stock_list(home, home_list, z_info->store_inven_max);
	if (home->stock_num) {
		/* Header */
		file_putf(fff, "  [Home Inventory]\n\n");

		/* Dump all available items */
		for (i = 0; i < z_info->store_inven_max; i++) {
			struct object *obj = home_list[i];
			if (!obj) break;
			object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
			file_putf(fff, "%c) %s\n", I2A(i), o_name);

			object_info_chardump(fff, obj, 5, 72);
		}

		/* Add an empty line */
		file_putf(fff, "\n\n");
	}

	/* Dump character history */
	dump_history(fff);
	file_putf(fff, "\n\n");

	/* Dump options */
	file_putf(fff, "  [Options]\n\n");

	/* Dump options */
	for (i = 0; i < OP_MAX; i++) {
		int opt;
		const char *title = "";
		switch (i) {
			case OP_INTERFACE: title = "User interface"; break;
			case OP_BIRTH: title = "Birth"; break;
		    default: continue;
		}

		file_putf(fff, "  [%s]\n\n", title);
		for (opt = 0; opt < OPT_MAX; opt++) {
			if (option_type(opt) != i) continue;

			file_putf(fff, "%-45s: %s (%s)\n",
			        option_desc(opt),
			        player->opts.opt[opt] ? "yes" : "no ",
			        option_name(opt));
		}

		/* Skip some lines */
		file_putf(fff, "\n");
	}

	mem_free(home_list);
}
Exemplo n.º 15
0
Arquivo: cmd4.c Projeto: jcubic/ToME
/*
 * Show previous messages to the user	-BEN-
 *
 * The screen format uses line 0 and (Term->hgt - 1) for headers and prompts,
 * skips line 1 and (Term->hgt - 2), and uses line 2 thru (Term->hgt - 3) for
 * old messages.
 *
 * This command shows you which commands you are viewing, and allows
 * you to "search" for strings in the recall.
 *
 * Note that messages may be longer than 80 characters, but they are
 * displayed using "infinite" length, with a special sub-command to
 * "slide" the virtual display to the left or right.
 *
 * Attempt to only hilite the matching portions of the string.
 *
 * Now taking advantages of big-screen. -pav-
 */
void do_cmd_messages(void)
{
	s32b i, j, k, n, q;
	s32b wid, hgt;

	char shower[80];
	char finder[80];

	/* Wipe finder */
	strcpy(finder, "");

	/* Wipe shower */
	strcpy(shower, "");


	/* Total messages */
	n = message_num();

	/* Start on first message */
	i = 0;

	/* Start at leftmost edge */
	q = 0;

	/* Enter "icky" mode */
	character_icky++;

	/* Save the screen */
	Term_save();

	/* Process requests until done */
	while (1)
	{
		/* Clear screen */
		Term_clear();

		/* Retrieve current screen size */
		Term_get_size(&wid, &hgt);

		/* Dump up to 20 (or more in bigscreen) lines of messages */
		for (j = 0; (j < (hgt - 4)) && (i + j < n); j++)
		{
			cptr msg = message_str(i + j);
			byte color = message_color(i + j);

			/* Apply horizontal scroll */
			msg = (strlen(msg) >= q) ? (msg + q) : "";

			/* Dump the messages, bottom to top */
			display_message(0, (hgt - 3) - j, strlen(msg), color, msg);

			/* Hilite "shower" */
			if (shower[0])
			{
				cptr str = msg;

				/* Display matches */
				while ((str = strstr(str, shower)) != NULL)
				{
					s32b len = strlen(shower);

					/* Display the match */
					Term_putstr(str - msg, (hgt - 3) - j, len, TERM_YELLOW, shower);

					/* Advance */
					str += len;
				}
			}
		}

		/* Display header XXX XXX XXX */
		prt(format("Message Recall (%d-%d of %d), Offset %d",
		           i, i + j - 1, n, q), 0, 0);

		/* Display prompt (not very informative) */
		prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", hgt - 1, 0);

		/* Get a command */
		k = inkey();

		/* Exit on Escape */
		if (k == ESCAPE) break;

		/* Hack -- Save the old index */
		j = i;

		/* Horizontal scroll */
		if (k == '4')
		{
			/* Scroll left */
			q = (q >= wid / 2) ? (q - wid / 2) : 0;

			/* Success */
			continue;
		}

		/* Horizontal scroll */
		if (k == '6')
		{
			/* Scroll right */
			q = q + wid / 2;

			/* Success */
			continue;
		}

		/* Hack -- handle show */
		if (k == '=')
		{
			/* Prompt */
			prt("Show: ", hgt - 1, 0);

			/* Get a "shower" string, or continue */
			if (!askfor_aux(shower, 80)) continue;

			/* Okay */
			continue;
		}

		/* Hack -- handle find */
		if (k == '/')
		{
			s16b z;

			/* Prompt */
			prt("Find: ", hgt - 1, 0);

			/* Get a "finder" string, or continue */
			if (!askfor_aux(finder, 80)) continue;

			/* Show it */
			strcpy(shower, finder);

			/* Scan messages */
			for (z = i + 1; z < n; z++)
			{
				cptr msg = message_str(z);

				/* Search for it */
				if (strstr(msg, finder))
				{
					/* New location */
					i = z;

					/* Done */
					break;
				}
			}
		}

		/* Recall 1 older message */
		if ((k == '8') || (k == '\n') || (k == '\r'))
		{
			/* Go newer if legal */
			if (i + 1 < n) i += 1;
		}

		/* Recall 10 older messages */
		if (k == '+')
		{
			/* Go older if legal */
			if (i + 10 < n) i += 10;
		}

		/* Recall one screen of older messages */
		if ((k == 'p') || (k == KTRL('P')) || (k == ' '))
		{
			/* Go older if legal */
			if (i + (hgt - 4) < n) i += (hgt - 4);
		}

		/* Recall one screen of newer messages */
		if ((k == 'n') || (k == KTRL('N')))
		{
			/* Go newer (if able) */
			i = (i >= (hgt - 4)) ? (i - (hgt - 4)) : 0;
		}

		/* Recall 10 newer messages */
		if (k == '-')
		{
			/* Go newer (if able) */
			i = (i >= 10) ? (i - 10) : 0;
		}

		/* Recall 1 newer messages */
		if (k == '2')
		{
			/* Go newer (if able) */
			i = (i >= 1) ? (i - 1) : 0;
		}

		/* Hack -- Error of some kind */
		if (i == j) bell();
	}

	/* Restore the screen */
	Term_load();

	/* Leave "icky" mode */
	character_icky--;
}
Exemplo n.º 16
0
/*
 * Hack -- Dump a character description file
 *
 * XXX XXX XXX Allow the "full" flag to dump additional info,
 * and trigger its usage from various places in the code.
 */
errr file_character(const char *path, bool full)
{
	int i, x, y;

	byte a;
	char c;

	ang_file *fp;

	struct store *st_ptr = &stores[STORE_HOME];

	char o_name[80];

	byte (*old_xchar_hook)(byte c) = Term.xchar_hook;

	char buf[1024];

	/* We use either ascii or system-specific encoding */
 	int encoding = OPT(xchars_to_file) ? SYSTEM_SPECIFIC : ASCII;

	/* Unused parameter */
	(void)full;


	/* Open the file for writing */
	fp = file_open(path, MODE_WRITE, FTYPE_TEXT);
	if (!fp) return (-1);

	/* Display the requested encoding -- ASCII or system-specific */
 	if (!OPT(xchars_to_file)) Term.xchar_hook = null;

	/* Begin dump */
	file_putf(fp, "  [%s Character Dump]\n\n", buildid);


	/* Display player */
	display_player(0);

	/* Dump part of the screen */
	for (y = 1; y < 23; y++)
	{
		/* Dump each row */
		for (x = 0; x < 79; x++)
		{
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			buf[x] = c;
		}

		/* Back up over spaces */
		while ((x > 0) && (buf[x-1] == ' ')) --x;

		/* Terminate */
		buf[x] = '\0';

		/* End the row */
		x_file_putf(fp, encoding, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fp, "\n");

	/* Display player */
	display_player(1);

	/* Dump part of the screen */
	for (y = 11; y < 20; y++)
	{
		/* Dump each row */
		for (x = 0; x < 39; x++)
		{
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			buf[x] = c;
		}

		/* Back up over spaces */
		while ((x > 0) && (buf[x-1] == ' ')) --x;

		/* Terminate */
		buf[x] = '\0';

		/* End the row */
		x_file_putf(fp, encoding, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fp, "\n");

	/* Dump part of the screen */
	for (y = 11; y < 20; y++)
	{
		/* Dump each row */
		for (x = 0; x < 39; x++)
		{
			/* Get the attr/char */
			(void)(Term_what(x + 40, y, &a, &c));

			/* Dump it */
			buf[x] = c;
		}

		/* Back up over spaces */
		while ((x > 0) && (buf[x-1] == ' ')) --x;

		/* Terminate */
		buf[x] = '\0';

		/* End the row */
		x_file_putf(fp, encoding, "%s\n", buf);
	}

	/* Skip some lines */
	file_putf(fp, "\n\n");


	/* If dead, dump last messages -- Prfnoff */
	if (p_ptr.is_dead)
	{
		i = messages_num();
		if (i > 15) i = 15;
		file_putf(fp, "  [Last Messages]\n\n");
		while (i-- > 0)
		{
			x_file_putf(fp, encoding, "> %s\n", message_str((s16b)i));
		}
		x_file_putf(fp, encoding, "\nKilled by %s.\n\n", p_ptr.died_from);
	}


	/* Dump the equipment */
	file_putf(fp, "  [Character Equipment]\n\n");
	for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++)
	{
		if (i == INVEN_TOTAL)
		{
			file_putf(fp, "\n\n  [Character Quiver]\n\n");
			continue;
		}
		object_desc(o_name, sizeof(o_name), &p_ptr.inventory[i],
				ODESC_PREFIX | ODESC_FULL);

		x_file_putf(fp, encoding, "%c) %s\n", index_to_label(i), o_name);
		if (p_ptr.inventory[i].kind)
			object_info_chardump(fp, &p_ptr.inventory[i], 5, 72);
	}

	/* Dump the inventory */
	file_putf(fp, "\n\n  [Character Inventory]\n\n");
	for (i = 0; i < INVEN_PACK; i++)
	{
		if (!p_ptr.inventory[i].kind) break;

		object_desc(o_name, sizeof(o_name), &p_ptr.inventory[i],
					ODESC_PREFIX | ODESC_FULL);

		x_file_putf(fp, encoding, "%c) %s\n", index_to_label(i), o_name);
		object_info_chardump(fp, &p_ptr.inventory[i], 5, 72);
	}
	file_putf(fp, "\n\n");


	/* Dump the Home -- if anything there */
	if (st_ptr.stock_num)
	{
		/* Header */
		file_putf(fp, "  [Home Inventory]\n\n");

		/* Dump all available items */
		for (i = 0; i < st_ptr.stock_num; i++)
		{
			object_desc(o_name, sizeof(o_name), &st_ptr.stock[i],
						ODESC_PREFIX | ODESC_FULL);
			x_file_putf(fp, encoding, "%c) %s\n", I2A(i), o_name);

			object_info_chardump(fp, &st_ptr.stock[i], 5, 72);
		}

		/* Add an empty line */
		file_putf(fp, "\n\n");
	}

	/* Dump character history */
	dump_history(fp);
	file_putf(fp, "\n\n");

	/* Dump options */
	file_putf(fp, "  [Options]\n\n");

	/* Dump options */
	for (i = OPT_BIRTH; i < OPT_BIRTH + N_OPTS_BIRTH; i++)
	{
		if (option_name(i))
		{
			file_putf(fp, "%-45s: %s (%s)\n",
			        option_desc(i),
			        op_ptr.opt[i] ? "yes" : "no ",
			        option_name(i));
		}
	}

	/* Skip some lines */
	file_putf(fp, "\n\n");

	/* Return to standard display */
 	Term.xchar_hook = old_xchar_hook;

	file_close(fp);


	/* Success */
	return (0);
}
Exemplo n.º 17
0
/**
 * Show previous messages to the user
 *
 * The screen format uses line 0 and 23 for headers and prompts,
 * skips line 1 and 22, and uses line 2 thru 21 for old messages.
 *
 * This command shows you which commands you are viewing, and allows
 * you to "search" for strings in the recall.
 *
 * Note that messages may be longer than 80 characters, but they are
 * displayed using "infinite" length, with a special sub-command to
 * "slide" the virtual display to the left or right.
 *
 * Attempt to only hilight the matching portions of the string.
 */
void do_cmd_messages(void)
{
  ui_event ke;
  
  int i, j, n, q;
  int wid, hgt;
  
  char shower[80];
  char finder[80];
  char p[80];  
  
  /* Wipe finder */
  my_strcpy(finder, "", sizeof(shower));
  
  /* Wipe shower */
  my_strcpy(shower, "", sizeof(finder));
  
  
  /* Total messages */
  n = messages_num();
  
  /* Start on first message */
  i = 0;
  
  /* Start at leftmost edge */
  q = 0;
  
  /* Get size */
  Term_get_size(&wid, &hgt);
  
  /* Prompt */
  strncpy(p, "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", 80);

  /* Save screen */
  screen_save();
  
  /* Adjust the buttons */
  button_backup_all();
  button_kill_all();
  button_add("ESC", ESCAPE);
  button_add("-", '-');
  button_add("=", '=');
  button_add("/", '/');
  button_add("p", 'p');
  button_add("n", 'n');
  button_add("+", '+');
  button_add("->", '6');
  button_add("<-", '4');
  p_ptr->redraw |= (PR_BUTTONS);

  /* Process requests until done */
  while (1)
    {
      /* Clear screen */
      Term_clear();
      
      /* Dump messages */
      for (j = 0; (j < hgt - 4) && (i + j < n); j++)
	{
	  const char *msg = message_str((s16b)(i+j));
	  byte attr = message_color((s16b)(i+j));
	  
	  /* Apply horizontal scroll */
	  msg = ((int)strlen(msg) >= q) ? (msg + q) : "";
	  
	  /* Dump the messages, bottom to top */
	  Term_putstr(0, hgt - 3 - j, -1, attr, msg);
	  
	  /* Hilight "shower" */
	  if (shower[0])
	    {
	      const char *str = msg;
	      
	      /* Display matches */
	      while ((str = strstr(str, shower)) != NULL)
		{
		  int len = strlen(shower);
		  
		  /* Display the match */
		  Term_putstr(str-msg, hgt - 3 - j, len, TERM_YELLOW, shower);
		  
		  /* Advance */
		  str += len;
		}
	    }
	}
      
      /* Display header XXX XXX XXX */
      prt(format("Message Recall (%d-%d of %d), Offset %d",
		 i, i + j - 1, n, q), 0, 0);
      
      /* Display prompt (not very informative) */
      prt(p, hgt - 1, 0);
      redraw_stuff(p_ptr);
      
      /* Get a command */
      ke = inkey_ex();
      
      /* Exit on Escape */
      if (ke.key.code == ESCAPE) break;
      
      /* Hack -- Save the old index */
      j = i;
      
      /* Horizontal scroll */
      if (ke.key.code == '4')
	{
	  /* Scroll left */
	  q = (q >= wid / 2) ? (q - wid / 2) : 0;
	  
	  /* Success */
	  continue;
	}
      
      /* Horizontal scroll */
      if (ke.key.code == '6')
	{
	  /* Scroll right */
	  q = q + wid / 2;
	  
	  /* Success */
	  continue;
	}
      
      /* Hack -- handle show */
      if (ke.key.code == '=')
	{
	  /* Prompt */
	  prt("Show: ", hgt - 1, 0);
	  
	  /* Get a "shower" string, or continue */
	  if (!askfor_aux(shower, sizeof shower, NULL)) continue;
	  
	  /* Okay */
	  continue;
	}
      
      /* Hack -- handle find */
      if (ke.key.code == '/')
	{
	  s16b z;
	  
	  /* Prompt */
	  prt("Find: ", hgt - 1, 0);
	  
	  /* Get a "finder" string, or continue */
	  if (!askfor_aux(finder, sizeof finder, NULL)) continue;
	  
	  /* Show it */
	  my_strcpy(shower, finder, sizeof(shower));
	  
	  /* Scan messages */
	  for (z = i + 1; z < n; z++)
	    {
	      const char *msg = message_str(z);
	      
	      /* Search for it */
	      if (strstr(msg, finder))
		{
		  /* New location */
		  i = z;
		  
		  /* Done */
		  break;
		}
	    }
	}
      
      /* Recall 20 older messages */
      if ((ke.key.code == 'p') || (ke.key.code == KTRL('P')) || (ke.key.code == ' '))
	{
	  /* Go older if legal */
	  if (i + 20 < n) i += 20;
	}
      
      /* Recall 10 older messages */
      if (ke.key.code == '+')
	{
	  /* Go older if legal */
	  if (i + 10 < n) i += 10;
	}
      
      /* Recall 1 older message */
      if ((ke.key.code == '8') || (ke.key.code == '\n') || (ke.key.code == '\r'))
	{
	  /* Go older if legal */
	  if (i + 1 < n) i += 1;
	}
      
      /* Recall 20 newer messages */
      if ((ke.key.code == 'n') || (ke.key.code == KTRL('N')))
	{
	  /* Go newer (if able) */
	  i = (i >= 20) ? (i - 20) : 0;
	}
      
      /* Recall 10 newer messages */
      if (ke.key.code == '-')
	{
	  /* Go newer (if able) */
	  i = (i >= 10) ? (i - 10) : 0;
	}
      
      /* Recall 1 newer messages */
      if (ke.key.code == '2')
	{
	  /* Go newer (if able) */
	  i = (i >= 1) ? (i - 1) : 0;
	}
      
      /* Scroll forwards or backwards using mouse clicks */
      if (ke.mouse.button)
      {
	  if (ke.mouse.y <= hgt / 2)
	  {
	      /* Go older if legal */
	      if (i + 20 < n) i += 20;
	  }
	  else
	  {
	      /* Go newer (if able) */
	      i = (i >= 20) ? (i - 20) : 0;
	  }
      }
      
      /* Hack -- Error of some kind */
      if (i == j) bell(NULL);
    }
  
  /* Adjust the buttons */
  button_restore();

  /* Load screen */
  screen_load();
}
Exemplo n.º 18
0
Arquivo: save.c Projeto: fph/mortsil
/*
 * Actually write a save-file
 */
static bool wr_savefile(void)
{
	int i;

	u32b now;

	u16b tmp16u;


	/* Guess at the current time */
	now = time((time_t *)0);


	/* Note the operating system */
	sf_xtra = 0L;

	/* Note when the file was saved */
	sf_when = now;

	/* Note the number of saves */
	sf_saves++;


	/*** Actually write the file ***/

	/* Dump the file header */
	xor_byte = 0;
	wr_byte(VERSION_MAJOR);
	xor_byte = 0;
	wr_byte(VERSION_MINOR);
	xor_byte = 0;
	wr_byte(VERSION_PATCH);
	xor_byte = 0;
	wr_byte(VERSION_EXTRA);


	/* Reset the checksum */
	v_stamp = 0L;
	x_stamp = 0L;


	/* Operating system */
	wr_u32b(sf_xtra);

	/* Time file last saved */
	wr_u32b(sf_when);

	/* Number of past lives */
	wr_u16b(sf_lives);

	/* Number of times saved */
	wr_u16b(sf_saves);

	// 8 spare bytes
	wr_u32b(0L);
	wr_u32b(0L);

	/* Write the RNG state */
	wr_randomizer();

	/* Write the boolean "options" */
	wr_options();

	/* Dump the number of "messages" */
	tmp16u = message_num();
	wr_u16b(tmp16u);

	/* Dump the messages (oldest first!) */
	for (i = tmp16u - 1; i >= 0; i--)
	{
		wr_string(message_str((s16b)i));
		wr_u16b(message_type((s16b)i));
	}


	/* Dump the monster lore */
	tmp16u = z_info->r_max;
	wr_u16b(tmp16u);
	for (i = 0; i < tmp16u; i++) wr_lore(i);

	/* Dump the object memory */
	tmp16u = z_info->k_max;
	wr_u16b(tmp16u);
	for (i = 0; i < tmp16u; i++) wr_xtra(i);

	/* Hack -- Dump the artefacts */
	tmp16u = z_info->art_max;
	wr_u16b(tmp16u);
	for (i = 0; i < tmp16u; i++)
	{
		artefact_type *a_ptr = &a_info[i];
		wr_byte(a_ptr->cur_num);
		wr_byte(a_ptr->found_num);
	}

	/* Write the "extra" information */
	wr_extra();

	/*Write the randarts*/
	wr_randarts();

	/*Copy the notes file into the savefile*/
	wr_notes();

	// Write the smithing item
	wr_item(smith_o_ptr);
	
	/* Write the inventory */
	for (i = 0; i < INVEN_TOTAL; i++)
	{
		object_type *o_ptr = &inventory[i];

		/* Skip non-objects */
		if (!o_ptr->k_idx) continue;

		/* Dump index */
		wr_u16b((u16b)i);

		/* Dump object */
		wr_item(o_ptr);
	}

	/* Add a sentinel */
	wr_u16b(0xFFFF);

	/* Player is not dead, write the dungeon */
	if (!p_ptr->is_dead)
	{
		/* Dump the dungeon */
		wr_dungeon();
	}


	/* Write the "value check-sum" */
	wr_u32b(v_stamp);

	/* Write the "encoded checksum" */
	wr_u32b(x_stamp);


	/* Error in save */
	if (ferror(fff) || (fflush(fff) == EOF)) return FALSE;

	/* Successful save */
	return TRUE;
}
Exemplo n.º 19
0
/*
 * Show previous messages to the user   -BEN-
 *
 * The screen format uses line 0 and 23 for headers and prompts,
 * skips line 1 and 22, and uses line 2 thru 21 for old messages.
 *
 * This command shows you which commands you are viewing, and allows
 * you to "search" for strings in the recall.
 *
 * Note that messages may be longer than 80 characters, but they are
 * displayed using "infinite" length, with a special sub-command to
 * "slide" the virtual display to the left or right.
 *
 * Attempt to only hilite the matching portions of the string.
 */
void do_cmd_messages(void)
{
        int i, j, k, n, q;

        char shower[80] = "";
        char finder[80] = "";


        /* Total messages */
        n = message_num();

        /* Start on first message */
        i = 0;

        /* Start at leftmost edge */
        q = 0;


        /* Enter "icky" mode */
        screen_icky = topline_icky = TRUE;

        /* Save the screen */
        Term_save();

        /* Process requests until done */
        while (1)
        {
                /* Clear screen */
                Term_clear();

                /* Dump up to 20 lines of messages */
                for (j = 0; (j < 20) && (i + j < n); j++)
                {
                        byte a = TERM_WHITE;

                        cptr str = message_str(i+j);
                        
                        /* Determine color */
                        message_color(str, &a);

                        /* Apply horizontal scroll */
                        str = (strlen(str) >= q) ? (str + q) : "";

                        /* Handle "shower" */
                        if (shower[0] && strstr(str, shower)) a = TERM_YELLOW;

                        /* Dump the messages, bottom to top */
                        Term_putstr(0, 21-j, -1, a, str);
                }

                /* Display header XXX XXX XXX */
                prt(format("Message Recall (%d-%d of %d), Offset %d",
                           i, i+j-1, n, q), 0, 0);

                /* Display prompt (not very informative) */
                prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", 23, 0);

                /* Get a command */
                k = inkey();

                /* Exit on Escape */
                if (k == ESCAPE) break;

                /* Hack -- Save the old index */
                j = i;

                /* Horizontal scroll */
                if (k == '4')
                {
                        /* Scroll left */
                        q = (q >= 40) ? (q - 40) : 0;

                        /* Success */
                        continue;
                }

                /* Horizontal scroll */
                if (k == '6')
                {
                        /* Scroll right */
                        q = q + 40;

                        /* Success */
                        continue;
                }

                /* Hack -- handle show */
                if (k == '=')
                {
                        /* Prompt */
                        prt("Show: ", 23, 0);

                        /* Get a "shower" string, or continue */
                        if (!askfor_aux(shower, 80, 0)) continue;

                        /* Okay */
                        continue;
                }

                /* Hack -- handle find */
                if (k == '/')
                {
                        int z;

                        /* Prompt */
                        prt("Find: ", 23, 0);

                        /* Get a "finder" string, or continue */
                        if (!askfor_aux(finder, 80, 0)) continue;

                        /* Scan messages */
                        for (z = i + 1; z < n; z++)
                        {
                                cptr str = message_str(z);

                                /* Handle "shower" */
                                if (strstr(str, finder))
                                {
                                        /* New location */
                                        i = z;

                                        /* Done */
                                        break;
                                }
                        }
                }

                /* Recall 1 older message */
                if ((k == '8') || (k == '\n') || (k == '\r'))
                {
                        /* Go newer if legal */
                        if (i + 1 < n) i += 1;
                }

                /* Recall 10 older messages */
                if (k == '+')
                {
                        /* Go older if legal */
                        if (i + 10 < n) i += 10;
                }

                /* Recall 20 older messages */
                if ((k == 'p') || (k == KTRL('P')) || (k == ' '))
                {
                        /* Go older if legal */
                        if (i + 20 < n) i += 20;
                }

                /* Recall 20 newer messages */
                if ((k == 'n') || (k == KTRL('N')))
                {
                        /* Go newer (if able) */
                        i = (i >= 20) ? (i - 20) : 0;
                }

                /* Recall 10 newer messages */
                if (k == '-')
                {
                        /* Go newer (if able) */
                        i = (i >= 10) ? (i - 10) : 0;
                }

                /* Recall 1 newer messages */
                if (k == '2')
                {
                        /* Go newer (if able) */
                        i = (i >= 1) ? (i - 1) : 0;
                }

                /* Hack -- Error of some kind */
                if (i == j) bell();
        }

        /* Restore the screen */
        Term_load();

        /* Leave "icky" mode */
        screen_icky = topline_icky = FALSE;

	/* Flush any queued events */
	Flush_queue();
}
Exemplo n.º 20
0
/*
 * Show previous messages to the user
 *
 * The screen format uses line 0 and 23 for headers and prompts,
 * skips line 1 and 22, and uses line 2 thru 21 for old messages.
 *
 * This command shows you which commands you are viewing, and allows
 * you to "search" for strings in the recall.
 *
 * Note that messages may be longer than 80 characters, but they are
 * displayed using "infinite" length, with a special sub-command to
 * "slide" the virtual display to the left or right.
 *
 * Attempt to only highlight the matching portions of the string.
 */
void do_cmd_messages(void)
{
	ui_event ke;

	bool more = TRUE;

	int i, j, n, q;
	int wid, hgt;

	char shower[80] = "";



	/* Total messages */
	n = messages_num();

	/* Start on first message */
	i = 0;

	/* Start at leftmost edge */
	q = 0;

	/* Get size */
	Term_get_size(&wid, &hgt);

	/* Save screen */
	screen_save();

	/* Process requests until done */
	while (more)
	{
		/* Clear screen */
		Term_clear();

		/* Dump messages */
		for (j = 0; (j < hgt - 4) && (i + j < n); j++)
		{
			const char *msg;
			const char *str = message_str(i + j);
			byte attr = message_color(i + j);
			u16b count = message_count(i + j);

			if (count == 1)
				msg = str;
			else
				msg = format("%s <%dx>", str, count);

			/* Apply horizontal scroll */
			msg = ((int)strlen(msg) >= q) ? (msg + q) : "";

			/* Dump the messages, bottom to top */
			Term_putstr(0, hgt - 3 - j, -1, attr, msg);

			/* Highlight "shower" */
			if (shower[0])
			{
				str = msg;

				/* Display matches */
				while ((str = my_stristr(str, shower)) != NULL)
				{
					int len = strlen(shower);

					/* Display the match */
					Term_putstr(str-msg, hgt - 3 - j, len, TERM_YELLOW, str);

					/* Advance */
					str += len;
				}
			}
		}

		/* Display header */
		prt(format("Message recall (%d-%d of %d), offset %d", i, i + j - 1, n, q), 0, 0);

		/* Display prompt (not very informative) */
		if (shower[0])
			prt("[Movement keys to navigate, '-' for next, '=' to find]", hgt - 1, 0);
		else
			prt("[Movement keys to navigate, '=' to find, or ESCAPE to exit]", hgt - 1, 0);
			

		/* Get a command */
		ke = inkey_ex();


		/* Scroll forwards or backwards using mouse clicks */
		if (ke.type == EVT_MOUSE) {
			if (ke.mouse.y <= hgt / 2) {
				/* Go older if legal */
				if (i + 20 < n)
					i += 20;
			} else {
				/* Go newer */
				i = (i >= 20) ? (i - 20) : 0;
			}
		} else if (ke.type == EVT_KBRD) {
			switch (ke.key.code) {
				case ESCAPE: {
					more = FALSE;
					break;
				}

				case '=': {
					/* Get the string to find */
					prt("Find: ", hgt - 1, 0);
					if (!askfor_aux(shower, sizeof shower, NULL)) continue;
		
					/* Set to find */
					ke.key.code = '-';
					break;
				}

				case ARROW_LEFT:
				case '4':
					q = (q >= wid / 2) ? (q - wid / 2) : 0;
					break;

				case ARROW_RIGHT:
				case '6':
					q = q + wid / 2;
					break;

				case ARROW_UP:
				case '8':
					if (i + 1 < n) i += 1;
					break;

				case ARROW_DOWN:
				case '2':
				case '\r':
				case '\n':
					i = (i >= 1) ? (i - 1) : 0;
					break;

				case KC_PGUP:
				case 'p':
				case ' ':
					if (i + 20 < n) i += 20;
					break;

				case KC_PGDOWN:
				case 'n':
					i = (i >= 20) ? (i - 20) : 0;
					break;
			}
		}

		/* Find the next item */
		if (ke.key.code == '-' && shower[0])
		{
			s16b z;

			/* Scan messages */
			for (z = i + 1; z < n; z++)
			{
				/* Search for it */
				if (my_stristr(message_str(z), shower))
				{
					/* New location */
					i = z;

					/* Done */
					break;
				}
			}
		}
	}

	/* Load screen */
	screen_load();
}
Exemplo n.º 21
0
/*
 * Recall the most recent message
 */
void do_cmd_message_one(void)
{
	/* Recall one message XXX XXX XXX */
	c_prt(message_color(0), format( "> %s", message_str(0)), 0, 0);
}
Exemplo n.º 22
0
Arquivo: save.c Projeto: dis-/hengband
/*!
 * @brief セーブデータの書き込み /
 * Actually write a save-file
 * @return 成功すればtrue
 */
static bool wr_savefile_new(void)
{
	int        i, j;

	u32b              now;

	byte            tmp8u;
	u16b            tmp16u;


	/* Compact the objects */
	compact_objects(0);
	/* Compact the monsters */
	compact_monsters(0);

	/* Guess at the current time */
	now = time((time_t *)0);


	/* Note the operating system */
	sf_system = 0L;

	/* Note when the file was saved */
	sf_when = now;

	/* Note the number of saves */
	sf_saves++;


	/*** Actually write the file ***/

	/* Dump the file header */
	xor_byte = 0;
	wr_byte(FAKE_VER_MAJOR);
	xor_byte = 0;
	wr_byte(FAKE_VER_MINOR);
	xor_byte = 0;
	wr_byte(FAKE_VER_PATCH);
	xor_byte = 0;

	/* Initial value of xor_byte */
	tmp8u = (byte)Rand_external(256);
	wr_byte(tmp8u);


	/* Reset the checksum */
	v_stamp = 0L;
	x_stamp = 0L;

	/* Write the savefile version for Hengband 1.1.1 and later */
	wr_byte(H_VER_EXTRA);
	wr_byte(H_VER_PATCH);
	wr_byte(H_VER_MINOR);
	wr_byte(H_VER_MAJOR);

	/* Operating system */
	wr_u32b(sf_system);


	/* Time file last saved */
	wr_u32b(sf_when);

	/* Number of past lives */
	wr_u16b(sf_lives);

	/* Number of times saved */
	wr_u16b(sf_saves);


	/* Space */
	wr_u32b(0L);
	wr_u16b(0);
	wr_byte(0);

#ifdef JP
# ifdef EUC
	/* EUC kanji code */
	wr_byte(2);
# endif
# ifdef SJIS
	/* SJIS kanji code */
	wr_byte(3);
# endif
#else
	/* ASCII */
	wr_byte(1);
#endif

	/* Write the RNG state */
	wr_randomizer();


	/* Write the boolean "options" */
	wr_options();


	/* Dump the number of "messages" */
	tmp16u = message_num();
	if (compress_savefile && (tmp16u > 40)) tmp16u = 40;
	wr_u16b(tmp16u);

	/* Dump the messages (oldest first!) */
	for (i = tmp16u - 1; i >= 0; i--)
	{
		wr_string(message_str((s16b)i));
	}


	/* Dump the monster lore */
	tmp16u = max_r_idx;
	wr_u16b(tmp16u);
	for (i = 0; i < tmp16u; i++) wr_lore(i);


	/* Dump the object memory */
	tmp16u = max_k_idx;
	wr_u16b(tmp16u);
	for (i = 0; i < tmp16u; i++) wr_xtra(i);

	/* Dump the towns */
	tmp16u = max_towns;
	wr_u16b(tmp16u);

	/* Dump the quests */
	tmp16u = max_quests;
	wr_u16b(tmp16u);

	/* Dump the quests */
	tmp8u = MAX_RANDOM_QUEST-MIN_RANDOM_QUEST;
	wr_byte(tmp8u);

	for (i = 0; i < max_quests; i++)
	{
		quest_type* const q_ptr = &quest[i];

		/* Save status for every quest */
		wr_s16b(q_ptr->status);

		/* And the dungeon level too */
		/* (prevents problems with multi-level quests) */
		wr_s16b(q_ptr->level);

		wr_byte(q_ptr->complev);
		wr_u32b(q_ptr->comptime);

		/* Save quest status if quest is running */
		if (q_ptr->status == QUEST_STATUS_TAKEN || q_ptr->status == QUEST_STATUS_COMPLETED || !is_fixed_quest_idx(i))
		{
			wr_s16b(q_ptr->cur_num);
			wr_s16b(q_ptr->max_num);
			wr_s16b(q_ptr->type);
			wr_s16b(q_ptr->r_idx);
			wr_s16b(q_ptr->k_idx);
			wr_byte(q_ptr->flags);
			wr_byte(q_ptr->dungeon);
		}
	}

	/* Dump the position in the wilderness */
	wr_s32b(p_ptr->wilderness_x);
	wr_s32b(p_ptr->wilderness_y);

	wr_byte(p_ptr->wild_mode);
	wr_byte(ambush_flag);

	wr_s32b(max_wild_x);
	wr_s32b(max_wild_y);

	/* Dump the wilderness seeds */
	for (i = 0; i < max_wild_x; i++)
	{
		for (j = 0; j < max_wild_y; j++)
		{
			wr_u32b(wilderness[j][i].seed);
		}
	}

	/* Hack -- Dump the artifacts */
	tmp16u = max_a_idx;
	wr_u16b(tmp16u);
	for (i = 0; i < tmp16u; i++)
	{
		artifact_type *a_ptr = &a_info[i];
		wr_byte(a_ptr->cur_num);
		wr_s16b(a_ptr->floor_id);
	}



	/* Write the "extra" information */
	wr_extra();

	/* Dump the "player hp" entries */
	tmp16u = PY_MAX_LEVEL;
	wr_u16b(tmp16u);
	for (i = 0; i < tmp16u; i++)
	{
		wr_s16b(p_ptr->player_hp[i]);
	}


	/* Write spell data */
	wr_u32b(p_ptr->spell_learned1);
	wr_u32b(p_ptr->spell_learned2);
	wr_u32b(p_ptr->spell_worked1);
	wr_u32b(p_ptr->spell_worked2);
	wr_u32b(p_ptr->spell_forgotten1);
	wr_u32b(p_ptr->spell_forgotten2);

	wr_s16b(p_ptr->learned_spells);
	wr_s16b(p_ptr->add_spells);

	/* Dump the ordered spells */
	for (i = 0; i < 64; i++)
	{
		wr_byte(p_ptr->spell_order[i]);
	}


	/* Write the inventory */
	for (i = 0; i < INVEN_TOTAL; i++)
	{
		object_type *o_ptr = &inventory[i];

		/* Skip non-objects */
		if (!o_ptr->k_idx) continue;

		/* Dump index */
		wr_u16b((u16b)i);

		/* Dump object */
		wr_item(o_ptr);
	}

	/* Add a sentinel */
	wr_u16b(0xFFFF);

	/* Note the towns */
	tmp16u = max_towns;
	wr_u16b(tmp16u);

	/* Note the stores */
	tmp16u = MAX_STORES;
	wr_u16b(tmp16u);

	/* Dump the stores of all towns */
	for (i = 1; i < max_towns; i++)
	{
		for (j = 0; j < MAX_STORES; j++)
		{
			wr_store(&town[i].store[j]);
		}
	}

	/* Write the pet command settings */
	wr_s16b(p_ptr->pet_follow_distance);
	wr_s16b(p_ptr->pet_extra_flags);

	/* Write screen dump for sending score */
	if (screen_dump && (p_ptr->wait_report_score || !p_ptr->is_dead))
	{
		wr_string(screen_dump);
	}
	else
	{
		wr_string("");
	}

	/* Player is not dead, write the dungeon */
	if (!p_ptr->is_dead)
	{
		/* Dump the dungeon */
		if (!wr_dungeon()) return FALSE;

		/* Dump the ghost */
		wr_ghost();

		/* No scripts */
		wr_s32b(0);
	}


	/* Write the "value check-sum" */
	wr_u32b(v_stamp);

	/* Write the "encoded checksum" */
	wr_u32b(x_stamp);


	/* Error in save */
	if (ferror(fff) || (fflush(fff) == EOF)) return FALSE;

	/* Successful save */
	return TRUE;
}
Exemplo n.º 23
0
/*
 * Hack -- Dump a character description file
 *
 * XXX XXX XXX Allow the "full" flag to dump additional info,
 * and trigger its usage from various places in the code.
 */
errr file_character(const char *path, bool full)
{
	int i, x, y;

	int a;
	wchar_t c;

	ang_file *fp;

	struct store *st_ptr = &stores[STORE_HOME];

	char o_name[80];

	char buf[1024];
	char *p;

	/* Unused parameter */
	(void)full;


	/* Open the file for writing */
	fp = file_open(path, MODE_WRITE, FTYPE_TEXT);
	if (!fp) return (-1);

	/* Begin dump */
	file_putf(fp, "  [%s Character Dump]\n\n", buildid);


	/* Display player */
	display_player(0);

	/* Dump part of the screen */
	for (y = 1; y < 23; y++)
	{
		p = buf;
		/* Dump each row */
		for (x = 0; x < 79; x++)
		{
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		x_file_putf(fp, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fp, "\n");

	/* Display player */
	display_player(1);

	/* Dump part of the screen */
	for (y = 11; y < 20; y++)
	{
		p = buf;
		/* Dump each row */
		for (x = 0; x < 39; x++)
		{
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		x_file_putf(fp, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fp, "\n");

	/* Dump part of the screen */
	for (y = 11; y < 20; y++)
	{
		p = buf;
		/* Dump each row */
		for (x = 0; x < 39; x++)
		{
			/* Get the attr/char */
			(void)(Term_what(x + 40, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		x_file_putf(fp, "%s\n", buf);
	}

	/* Skip some lines */
	file_putf(fp, "\n\n");


	/* If dead, dump last messages -- Prfnoff */
	if (p_ptr->is_dead)
	{
		i = messages_num();
		if (i > 15) i = 15;
		file_putf(fp, "  [Last Messages]\n\n");
		while (i-- > 0)
		{
			x_file_putf(fp, "> %s\n", message_str((s16b)i));
		}
		x_file_putf(fp, "\nKilled by %s.\n\n", p_ptr->died_from);
	}


	/* Dump the equipment */
	file_putf(fp, "  [Character Equipment]\n\n");
	for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++)
	{
		if (i == INVEN_TOTAL)
		{
			file_putf(fp, "\n\n  [Character Quiver]\n\n");
			continue;
		}
		object_desc(o_name, sizeof(o_name), &p_ptr->inventory[i],
				ODESC_PREFIX | ODESC_FULL);

		x_file_putf(fp, "%c) %s\n", index_to_label(i), o_name);
		if (p_ptr->inventory[i].kind)
			object_info_chardump(fp, &p_ptr->inventory[i], 5, 72);
	}

	/* Dump the inventory */
	file_putf(fp, "\n\n  [Character Inventory]\n\n");
	for (i = 0; i < INVEN_PACK; i++)
	{
		if (!p_ptr->inventory[i].kind) break;

		object_desc(o_name, sizeof(o_name), &p_ptr->inventory[i],
					ODESC_PREFIX | ODESC_FULL);

		x_file_putf(fp, "%c) %s\n", index_to_label(i), o_name);
		object_info_chardump(fp, &p_ptr->inventory[i], 5, 72);
	}
	file_putf(fp, "\n\n");


	/* Dump the Home -- if anything there */
	if (st_ptr->stock_num)
	{
		/* Header */
		file_putf(fp, "  [Home Inventory]\n\n");

		/* Dump all available items */
		for (i = 0; i < st_ptr->stock_num; i++)
		{
			object_desc(o_name, sizeof(o_name), &st_ptr->stock[i],
						ODESC_PREFIX | ODESC_FULL);
			x_file_putf(fp, "%c) %s\n", I2A(i), o_name);

			object_info_chardump(fp, &st_ptr->stock[i], 5, 72);
		}

		/* Add an empty line */
		file_putf(fp, "\n\n");
	}

	/* Dump character history */
	dump_history(fp);
	file_putf(fp, "\n\n");

	/* Dump options */
	file_putf(fp, "  [Options]\n\n");

	/* Dump options */
	for (i = 0; i < OPT_PAGE_MAX - 1; i++) {
		int j;
		const char *title = "";
		switch (i) {
			case 0: title = "Interface"; break;
			case 1: title = "Warning"; break;
			case 2: title = "Birth"; break;
		}

		file_putf(fp, "  [%s]\n\n", title);
		for (j = 0; j < OPT_PAGE_PER; j++) {
			int opt = option_page[i][j];
			if (!option_name(opt)) continue;

			file_putf(fp, "%-45s: %s (%s)\n",
			        option_desc(opt),
			        op_ptr->opt[opt] ? "yes" : "no ",
			        option_name(opt));
		}

		/* Skip some lines */
		file_putf(fp, "\n");
	}

	file_close(fp);


	/* Success */
	return (0);
}
Exemplo n.º 24
0
int main()
{
    std::string name = "BrickyBot";
    std::string source = ":BrickyBot!~BrickyBot@BrickHouse";
    std::string server = "irc.p2p-network.net";
    std::string port = "6667";
    std::string channel = "#MyLittleAlcoholic";
    bool auto_reconnect = false;
    
    // Load and parse the options file for configurability
    std::vector<std::pair<std::string, std::string> > options = get_pairs_from_file("data/options");
    for (std::vector<std::pair<std::string, std::string> >::iterator options_it = options.begin(); options_it != options.end(); options_it++)
    {
        if ((*options_it).first == "name") name = (*options_it).second;
        else if ((*options_it).first == "source") source = (*options_it).second;
        else if ((*options_it).first == "server") server = (*options_it).second;
        else if ((*options_it).first == "port") port = (*options_it).second;
        else if ((*options_it).first == "channel") channel = (*options_it).second;
        else if ((*options_it).first == "auto_reconnect" && (*options_it).second == "true") auto_reconnect = true;
        else if ((*options_it).first == "debug" && (*options_it).second == "true") debug = true;
    }

    // initialize vectors    
    std::vector<std::string> operators = get_vector_from_file("data/operators");
    std::vector<std::string> episodes = get_vector_from_file("data/pony_episodes");
    std::vector<boost::tuple<std::string, uint16_t, time_t> > drinks = get_counts_from_tuples(get_tuples_from_file("data/drinkcount"));
    std::vector<std::pair<std::string, std::string> > responses = get_pairs_from_file("data/responses");
    std::vector<boost::tuple<std::string, uint16_t, time_t> > hits = get_counts_from_tuples(get_tuples_from_file("data/hitcount"));
    
    // set up signal handlers
    signal(SIGABRT, handleSignal);
    signal(SIGINT, handleSignal);
    signal(SIGTERM, handleSignal);
    
    try
    {
        // networking shit
        boost::asio::io_service io_service;
        boost::asio::ip::tcp::resolver resolver(io_service);
        boost::asio::ip::tcp::resolver::query query(server, port);
        boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        boost::asio::ip::tcp::socket socket(io_service);
        boost::asio::connect(socket, endpoint_iterator);

        boost::system::error_code ignored_error;
        uint64_t num_in = 0;
        bool first_ping = false;
        bool in_channel = false;
        
        while (running)
        {
            // Get a message from the server
            boost::array<char, 1024> buf;
            boost::system::error_code error;
            size_t len = socket.read_some(boost::asio::buffer(buf), error);

            // Check for an error or a closed connection
            if (error == boost::asio::error::eof)
            {
                // Connection closed cleanly by peer
                running = false;
            }
            else if (error)
            {
                // Some other dipshit error
                throw boost::system::system_error(error);
            }
            else
            {
                // No error. Parse the message.
                // First form a string from the char array
                std::string message_str(buf.begin(), buf.begin() + len);

                // Tokenize the string for multiple messages
                boost::char_separator<char> msg_sep("\r\n");
                boost::tokenizer<boost::char_separator<char> > msg_tok(message_str, msg_sep);

                // Place all the tokens into a vector
                std::vector<std::string> message_strings;
                for (boost::tokenizer<boost::char_separator<char> >::iterator it = msg_tok.begin(); it != msg_tok.end(); ++it)
                    message_strings.push_back(*it);

                // Process each message
                for (uint16_t i = 0; i < message_strings.size(); ++i)
                {
                    dbgPrint("incoming: %s\n", message_strings[i].c_str());

                    // Tokenize the message
                    boost::char_separator<char> sep(" ");
                    boost::tokenizer<boost::char_separator<char> > tok(message_strings[i], sep);
                    std::vector<std::string> tokens;
                    for (boost::tokenizer<boost::char_separator<char> >::iterator it = tok.begin(); it != tok.end(); ++it)
                        tokens.push_back(*it);

                    // Now process the message.
                    if (tokens[0] == "PING")
                    {
                        // Build a new string consisting of PONG followed by everything else
                        std::string send_str = "PONG";

                        for (uint16_t j = 1; j < tokens.size(); ++j)
                            send_str += " " + tokens[j];

                        // Add the carriage return and newline, as per IRC protocol
                        send_str += "\r\n";

                        // Send it to the server
                        boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);

                        first_ping = true;
                    }

                    num_in++;

                    
                    // Stupid IRC bullshit. Send some info after getting three messages.
                    if (num_in == 3)
                    {
                        // Send the USER/NICK message pair after 3 receives
                        // (What a w***e; receieves three times before telling its name...)
                        std::string nick_msg_str = "NICK " + name + "\r\n";
                        std::string user_msg_str = "USER " + name + " 0 * :" + name + "\r\n";
                        boost::asio::write(socket, boost::asio::buffer(nick_msg_str), ignored_error);
                        boost::asio::write(socket, boost::asio::buffer(user_msg_str), ignored_error);
                    }

                    // Join the channel when appropriate
                    if (first_ping && !in_channel)
                    {
                        // Connect after being pinged
                        std::string send_str = source + " JOIN :" + channel + "\r\n";
                        boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);

                        // wait a bit...
                        //boost::this_thread::sleep(boost::posix_time::milliseconds(1000));

                        in_channel = true;
                    }

                    // Bot is in the channel. The interesting shit is here
                    if (in_channel)
                    {
                        // Used to send messages
                        std::string send_str;

                        if (tokens[1] == "PRIVMSG") // gettin a message
                        {
                            // Get the name of the sending user
                            boost::char_separator<char> user_tok_sep(":!");
                            boost::tokenizer<boost::char_separator<char> > user_tok(tokens[0], user_tok_sep);
                            std::string sending_user = *(user_tok.begin());
                            
                            // Check whether the sending user is an operator
                            bool user_is_operator = (std::find(operators.begin(), operators.end(), sending_user) != operators.end());
                            
                            // Find the start of the text
                            uint16_t chat_start_index = 2;
                            while (tokens[chat_start_index][0] != ':') ++chat_start_index;
                            
                            // Add the first token (the start of the message) and remove the leading colon
                            std::string chat_text = tokens[chat_start_index];
                            chat_text.erase(0, 1);
                            
                            for (uint16_t chat_text_index = chat_start_index + 1; chat_text_index < tokens.size(); ++chat_text_index)
                            {
                                chat_text += " " + tokens[chat_text_index];
                            }

                            boost::char_separator<char> chat_sep(" ");
                            boost::tokenizer<boost::char_separator<char> > chat_tok(chat_text, chat_sep);
                            std::string chat_command = chat_text;
                            
                            int16_t chat_arg = -1;
                            
                            if (std::distance(chat_tok.begin(), chat_tok.end()) > 0)
                            {
                                chat_command =  *(chat_tok.begin());
                                
                                boost::tokenizer<boost::char_separator<char> >::iterator chat_tok_it = chat_tok.begin();
                                if (++chat_tok_it != chat_tok.end())
                                {
                                    try
                                    {
                                        chat_arg = boost::lexical_cast<int16_t>(*chat_tok_it);
                                    }
                                    catch (boost::bad_lexical_cast &)
                                    {
                                        BB
                                    }
                                }
                                
                                if (chat_arg < -1) chat_arg = -1;
                            }
                                
                            /*
                             *    This is where the bot actually does interesting things.
                             *    ---AT THIS INDENTATION, MOTHERFUCKERS.---
                             */
                            
                            // quit if an operator tells it to
                            if (boost::iequals(chat_text, name + ": quit") && user_is_operator)
                            {
                                send_str = source + " QUIT " + channel + " :quitting\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                                running = false;
                            }
                            
                            // reload operators file when ordered to by an operator
                            if (boost::iequals(chat_text, name + ": reload ops") && user_is_operator)
                            {
                                operators =  get_vector_from_file("data/operators");
                                send_str = source + " PRIVMSG " + channel + " :Reloaded operators.\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }

                            // .poni
                            if (boost::iequals(chat_command, ".poni"))
                            {
                                // pick a random episode
                                int episode = rand() % episodes.size();
                                send_str = source + " PRIVMSG " + channel + " :" + episodes[episode] + "\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                                
                            }
                            
                            // reload mlp episode list when ordered to by an operator
                            if (boost::iequals(chat_text, name + ": reload poni") && user_is_operator)
                            {
                                episodes =  get_vector_from_file("data/pony_episodes");
                                send_str = source + " PRIVMSG " + channel + " :Reloaded poni.\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            if (boost::iequals(chat_command, ".shot") || boost::iequals(chat_command, ".drink"))
                            {
                                // Find the user in the vector
                                int32_t user_index = get_user_index_in_counts(sending_user, drinks);
                                uint16_t current_drink_count;
                                
                                // If the user is already in the vector, increment the count and update the time.
                                // Otherwise, add the user and initialize them.
                                if (user_index != -1)
                                {
                                    time_t rawtime;
                                    time (&rawtime);
                                    
                                    drinks[user_index].get<1>() += chat_arg == -1? 1: chat_arg; 
                                    current_drink_count = boost::get<1>(drinks[user_index]);
                                    drinks[user_index].get<2>() = rawtime;
                                    // drinks[user_index].second += chat_arg == -1? 1: chat_arg;
                                    // current_drink_count = drinks[user_index].second;
                                }
                                else
                                {  ///////// Found a bug: if the user isn't in the array and adds more than one, it will only count as one, but
                                   ///////// it will say that it added however many it said it would. or so I think. I'm pretty drunk right now.
                                   time_t rawtime;
                                   time (&rawtime);
                                
                                   drinks.push_back(boost::make_tuple(sending_user, 1, rawtime));
                                    //drinks.push_back(std::make_pair(sending_user, 1));
                                    current_drink_count = chat_arg == -1? 1 : chat_arg;
                                }
                                
                                
                                // Write the changes to disk
                                write_counts(drinks, "data/drinkcount");
                                
                                // Convert the number of drinks into a string
                                std::ostringstream num_to_str;
                                num_to_str << current_drink_count;
                                std::string drink_count_str = num_to_str.str();
                                
                                // send the current number of drinks
                                send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at " +
                                        drink_count_str + " drink(s).\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            if (boost::iequals(chat_command, ".weed") || boost::iequals(chat_command, ".hit") || boost::iequals(chat_command, ".toke"))
                            {
                                // Find the user in the vector
                                int32_t user_index = get_user_index_in_counts(sending_user, hits);
                                uint16_t current_hit_count;
                                
                                // If the user is already in the vector, increment the count.
                                // Otherwise, add the user and initialize them with one drink.
                                if (user_index != -1)
                                {
                                    time_t rawtime;
                                    time (&rawtime);  
                                    
                                    hits[user_index].get<1>() += chat_arg == -1? 1: chat_arg;
                                    current_hit_count = boost::get<1>(hits[user_index]);
                                    hits[user_index].get<2>() = rawtime;
                                    //hits[user_index].second += chat_arg == -1? 1: chat_arg;
                                    //current_hit_count = hits[user_index].second;
                                }
                                else
                                {  ///////// Found a bug: if the user isn't in the array and adds more than one, it will only count as one, but
                                   ///////// it will say that it added however many it said it would. or so I think. I'm pretty drunk right now.
                                   time_t rawtime;
                                   time (&rawtime);  
                                   
                                    hits.push_back(boost::make_tuple(sending_user, 1, rawtime));
                                    //hits.push_back(std::make_pair(sending_user, 1));
                                    current_hit_count = chat_arg == -1? 1: chat_arg;
                                }

                                
                                // Write the changes to disk
                                 write_counts(hits, "data/hitcount");
                                
                                // Convert the number of drinks into a string
                                std::ostringstream num_to_str;
                                num_to_str << current_hit_count;
                                std::string hit_count_str = num_to_str.str();
                                
                                // send the current number of drinks
                                send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at " +
                                        hit_count_str + " hit(s).\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);                                
                            }
                            
                            if (boost::iequals(chat_command, ".reset"))
                            {
                                ////////////////// Reset Drink Count
                                
                                // Find the user in the vector
                                int32_t user_index = get_user_index_in_counts(sending_user, drinks);
                                
                                // set that user's shot/drink count to zero
                                if (user_index != -1)
                                {
                                    //drinks[user_index].second = 0;
                                    drinks[user_index].get<1>() = 0;
                                }
                                else
                                {
                                    time_t rawtime;
                                    time(&rawtime);
                                    //drinks.push_back(std::make_pair(sending_user, 0));
                                    drinks.push_back(boost::make_tuple(sending_user, 0, rawtime)); 
                                }
                                
                                // write changes to disk
                                write_counts(drinks, "data/drinkcount");
                                
                                ////////////////// Reset Hit Count
                                
                                // Find the user in the vector
                                user_index = get_user_index_in_counts(sending_user, hits);
                                
                                // set that user's hit count to zero
                                if (user_index != -1)
                                {
                                    //hits[user_index].second = 0;
                                    hits[user_index].get<1>() = 0;
                                }
                                else
                                {
                                    time_t rawtime;
                                    time(&rawtime);
                                    //hits.push_back(std::make_pair(sending_user, 0));
                                    hits.push_back(boost::make_tuple(sending_user, 0, rawtime));
                                }
                                
                                // write changes to disk
                                write_counts(hits, "data/hitcount");
                                
                                // send acknowledgement
                                send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at 0 drinks and 0 hits.\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            
                            
                            // Print user's counts
                            if (boost::iequals(chat_command, ".count"))
                            {
                                // Find the user in the vector
                                int32_t user_index = get_user_index_in_counts(sending_user, drinks);
                                
                                send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": you are now at ";
                                
                                if (user_index != -1)
                                {
                                    std::ostringstream num_to_str;
                                    //num_to_str << drinks[user_index].second;
                                    num_to_str << drinks[user_index].get<1>();
                                    send_str += num_to_str.str();
                                }
                                else
                                {
                                    send_str += "0";
                                }

                                send_str += " drinks and ";
                                
                                user_index = get_user_index_in_counts(sending_user, hits);
                                
                                if (user_index != -1)
                                {
                                    std::ostringstream num_to_str;
                                    //num_to_str << hits[user_index].second;
                                    num_to_str << hits[user_index].get<1>();
                                    send_str += num_to_str.str();
                                }
                                else
                                {
                                    send_str += "0";
                                }
                                
                                send_str += " hits.\r\n";

                                
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            // Print the time of the user's last count update
                            if (boost::iequals(chat_command, ".lastdrink"))
                            {
                                int32_t user_index = get_user_index_in_counts(sending_user, drinks);
                                
                                send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": ";
                                
                                if (user_index != -1)
                                {
                                    if (boost::get<1>(drinks[user_index]) > 0)
                                    {
                                        send_str += "Last counted drink was at " + std::string(ctime(&(boost::get<2>(drinks[user_index])))) + ".\r\n";
                                    }
                                    else
                                    {
                                        send_str += "You have no counted drinks.\r\n";
                                    }
                                }
                                else
                                {
                                    send_str += "You have no counted drinks.\r\n";
                                }
                                
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                                
                            }
                            if (boost::iequals(chat_command, ".lasthit"))
                            {
                                int32_t user_index = get_user_index_in_counts(sending_user, drinks);
                                
                                send_str = source + " PRIVMSG " + channel + " :" + sending_user + ": ";
                                
                                if (user_index != -1)
                                {
                                    if (boost::get<1>(hits[user_index]) > 0)
                                    {
                                        send_str += "Last counted hit was at " + std::string(ctime(&(boost::get<2>(hits[user_index])))) + ".\r\n";
                                    }
                                    else
                                    {
                                        send_str += "You have no counted hits.\r\n";
                                    }
                                }
                                else
                                {
                                    send_str += "You have no counted hits.\r\n";
                                }
                                
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            
                            // Print the channel's total number of recorded drinks
                            if (boost::iequals(chat_command, ".chtotal"))
                            {
                                uint32_t total = 0;
                                //for (std::vector<std::pair<std::string, uint16_t> >::iterator drinks_it = drinks.begin(); drinks_it != drinks.end(); drinks_it++)
                                for (std::vector<boost::tuple<std::string, uint16_t, time_t> >::iterator drinks_it = drinks.begin(); drinks_it != drinks.end(); drinks_it++)
                                {
                                    //total += (*drinks_it).second;
                                    total += boost::get<1>(*drinks_it);
                                }
                                
                                std::ostringstream num_to_str;
                                num_to_str << total;
                                send_str = source + " PRIVMSG " + channel + " :Total drinks: " + num_to_str.str() + "; ";
                                
                                total = 0;
                                //for (std::vector<std::pair<std::string, uint16_t> >::iterator hits_it = hits.begin(); hits_it != hits.end(); hits_it++)
                                for (std::vector<boost::tuple<std::string, uint16_t, time_t> >::iterator hits_it = hits.begin(); hits_it != hits.end(); hits_it++)
                                {
                                    //total += (*hits_it).second;
                                    total += boost::get<1>(*hits_it);
                                }
                                
                                std::ostringstream num_to_str2;
                                num_to_str2 << total;
                                send_str += "Total hits: " + num_to_str2.str() + "\r\n";
                                
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            // Send all the drink info
                            if (boost::iequals(chat_command, ".chdrinks"))
                            {
                                send_str = source + " PRIVMSG " + channel + " :Channel Drinks: ";
                                
                                for (uint16_t i = 0; i < drinks.size(); i++)
                                {
                                    //if (drinks[i].second > 0)
                                    if (drinks[i].get<1>() > 0)
                                    {
                                        std::ostringstream num_to_str;
                                        //num_to_str << drinks[i].second;
                                        num_to_str <<  boost::get<1>(drinks[i]);
                                        //send_str += drinks[i].first + ": " + num_to_str.str() + ". ";
                                        send_str += boost::get<0>(drinks[i]) + ": " + num_to_str.str() + ". ";
                                    }
                                }
                                
                                send_str += "\r\n";
                                
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }

                            // Send all the hits info
                            if (boost::iequals(chat_command, ".chhits"))
                            {
                                send_str = source + " PRIVMSG " + channel + " :Channel Hits: ";
                                
                                for (uint16_t i = 0; i < hits.size(); i++)
                                {
                                    //if (hits[i].second > 0)
                                    if (hits[i].get<1>() > 0)
                                    {
                                        std::ostringstream num_to_str;
                                        //num_to_str << hits[i].second;
                                        num_to_str << boost::get<1>(drinks[i]);
                                        //send_str += hits[i].first + ": " + num_to_str.str() + ". ";
                                        send_str += boost::get<0>(drinks[i]) + ": " + num_to_str.str() + ". ";
                                    }
                                }
                                
                                send_str += "\r\n";
                                
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                             
                            // Operator command to reset all drinks
                            if (boost::iequals(chat_text, name + ": reset all drinks") && user_is_operator)
                            {
                                for (uint16_t i = 0; i < drinks.size(); i++)
                                {
                                    drinks[i].get<1>() = 0;
                                    // drinks[i].second = 0;
                                }
                                
                                write_counts(drinks, "data/drinkcount");
                                
                                send_str = source + " PRIVMSG " + channel + " :All drinks were reset.\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            // Operator command to reset all hits
                            if (boost::iequals(chat_text, name + ": reset all hits") && user_is_operator)
                            {
                                for (uint16_t i = 0; i < hits.size(); i++)
                                {
                                    //hits[i].second = 0;
                                    hits[i].get<1>() = 0;
                                }
                                
                                write_counts(hits, "data/hitcount");
                                
                                send_str = source + " PRIVMSG " + channel + " :All hits were reset.\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            // Operator command to reset both counters
                            if (boost::iequals(chat_text, name + ": reset all") && user_is_operator)
                            {
                                for (uint16_t i = 0; i < drinks.size(); i++)
                                {
                                    //drinks[i].second = 0;
                                    drinks[i].get<1>() = 0;
                                }
                                
                                write_counts(drinks, "data/drinkcount");
                                
                                
                                for (uint16_t i = 0; i < hits.size(); i++)
                                {
                                    //hits[i].second = 0;
                                    hits[i].get<1>() = 0;
                                    
                                }
                                
                                write_counts(hits, "data/hitcount");   
                                
                                send_str = source + " PRIVMSG " + channel + " :All drinks and hits were reset.\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            // modifying responses while running
                            if (boost::iequals(chat_text, name + ": reload responses") && user_is_operator)
                            {
                                responses = get_pairs_from_file("data/responses");
                                send_str = source + " PRIVMSG " + channel + " :Reloaded responses.\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            
                            // simple response commands
                            for (std::vector<std::pair<std::string, std::string> >::iterator resp_it = responses.begin(); resp_it != responses.end(); resp_it++)
                            {
                                if (boost::iequals(chat_command, (*resp_it).first))
                                {
                                    send_str = source + " PRIVMSG " + channel + " :" + (*resp_it).second + "\r\n";
                                    boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                                }
                            }
                        }
                        else if (tokens[1] == "KICK" && tokens[3] == name) // The bot was kicked
                        {
                            boost::char_separator<char> user_tok_sep(":!");
                            boost::tokenizer<boost::char_separator<char> > user_tok(tokens[0], user_tok_sep);
                            std::string sending_user = *(user_tok.begin());
                            bool user_is_operator = (std::find(operators.begin(), operators.end(), sending_user) != operators.end());

                            if (auto_reconnect && !user_is_operator)
                            {
                                // rejoin the channel
                                std::string send_str = source + " JOIN :" + channel + "\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                            }
                            else
                            {
                                // don't rejoin; just quit
                                send_str = source + " QUIT " + channel + " :quitting\r\n";
                                boost::asio::write(socket, boost::asio::buffer(send_str), ignored_error);
                                running = false;
                            }
                        }
                    }
                }
            }