示例#1
0
文件: chess.cpp 项目: cycad/opencore
/*
 * 'c' is the attackers color.
 * kingx and kingy is the target king location.
 */
static
bool
IsCheckmatedBy(BOARD b, COLOR c, int kingx, int kingy)
{
	struct timeval tv;
	gettimeofday(&tv, NULL);

	COLOR defender = GetOppositeColor(c);

	PIECE *p;
	// for each piece on the board that is defending
	for (int x = 0; x < 8; ++x)
	for (int y = 0; y < 8; ++y) {
		p = GetPieceAt(b, x, y);
		if (p->color != defender) {
			continue;
		}

		// for each tile on the board, see if that piece can move there
		for (int j = 0; j < 8; ++j)
		for (int i = 0; i < 8; ++i) {
			if (PieceCanAttack(b, p->color, p->type, x, y, i, j) == true &&
			    GetPieceAt(b, i, j)->color != p->color) {
				PIECE old_p = *GetPieceAt(b, x, y);
				PIECE old_t = *GetPieceAt(b, i, j);

				// temporarily make the move
				SetPieceAt(b, x, y, COLOR_NONE, TYPE_NONE);
				SetPieceAt(b, i, j, old_p.color, old_p.type);

				// see if the move cancels check
				bool is_mate = true;
				int kx, ky;
				FindKing(b, defender, &kx, &ky);
				if (IsCoordAttackedBy(b, c, kx, ky) == false) {
					is_mate = false;
				}
				
				// revert the pieces
				SetPieceAt(b, x, y, old_p.color, old_p.type);
				SetPieceAt(b, i, j, old_t.color, old_t.type);

				if (is_mate == false) {
					struct timeval tv2;
					gettimeofday(&tv2, NULL);
					LogFmt(OP_MOD, "Checkmate Calculation: %lu.%06lu", tv2.tv_sec - tv.tv_sec, tv2.tv_usec - tv.tv_usec);
					return false;
				}
			}
		}
	}

	struct timeval tv2;
	gettimeofday(&tv2, NULL);

	LogFmt(OP_MOD, "Checkmate Calculation: %lu.%06lu", tv2.tv_sec - tv.tv_sec, tv2.tv_usec - tv.tv_usec);

	return true;
}
示例#2
0
void
StopBot(char *reason) 
{
	THREAD_DATA *td = get_thread_data();

	LogFmt(OP_MOD, "Shutting down: %s", reason ? reason : "Unspecified");
	td->running = -1;
}
示例#3
0
void
go(THREAD_DATA *td, SHIP ship, char *arena)
{
	strlcpy(td->arena_change_request, arena ? arena : td->login->arenaname, 16);

	LogFmt(OP_REF, "Changing arenas: %s", td->arena_change_request);
	pkt_send_arena_login(ship, td->arena_change_request);

	player_simulate_player_leaves(td, true);
}
示例#4
0
/*
 * Queue a packet 'p' with sending priority 'priority'. 'p' must point
 * to a packet allocated with allocate_packet().
 */
void
queue_packet(PACKET *p, int priority)
{
	assert(p->len <= 255);

	THREAD_DATA::net_t *n = get_thread_data()->net;

	if (priority == SP_HIGH)
		n->queues->h_prio->push_back(p);
	else if (priority == SP_NORMAL)
		n->queues->n_prio->push_back(p);	
	else if (priority == SP_DEFERRED) {
		LogFmt(OP_HSMOD, "Upgrading unreliable deferred packet to reliable");
		n->queues->d_prio->push_back(p);
	}
}
示例#5
0
/*
 * Check the get_file() queue and if there are entries, initiate
 * a file transfer.
 */
void
try_get_next_file(THREAD_DATA *td)
{
	THREAD_DATA::net_t *n = td->net;
	THREAD_DATA::net_t::chunk_in_t *ci = n->chunk_i;

	if (ci->in_use == 0 && ci->file_list->empty() == false) {
		DOWNLOAD_ENTRY *fe = &*ci->file_list->begin();
		LogFmt(OP_SMOD, "Initiating file download: %s", fe->name);
		if (strlen(fe->initiator) > 0) {
			RmtMessageFmt(fe->initiator, "Initiating file download: %s", fe->name);
		}
		PubMessageFmt("*getfile %s", fe->name);
		strlcpy(ci->initiator, fe->initiator, 24);
		ci->file_list->erase(ci->file_list->begin());
		ci->in_use = 1;
	}
}
示例#6
0
/*
 * The format of streams is:
 *
 * [0x00][0x0A][content length][data chunk ...]
 * Conforming to format string "AACZ"
 * Content length is the size of all data chunks combined (not
 * including headers)
 *
 * It is repeated for the entire size of the file.
 *
 * The format of file transfers is:
 * [0x16][char filename[16][data]
 * Format is "AZ16Z"
 * It is written as one giant packet encoded in a stream.
 * This can transfer up to 20mb files.
 */
int
queue_send_file(THREAD_DATA *td, const char *filename, const char *initiator)
{
	THREAD_DATA::net_t::send_file_data_t *sfd = td->net->send_file_data;

	if (strlen(filename) > 15) return 0;

	UPLOAD_DATA *ud = (UPLOAD_DATA*)xmalloc(sizeof(UPLOAD_DATA));
		
	strlcpy(ud->filename, filename, 64);
	strlcpy(ud->initiator, initiator ? initiator : "", 24);

	LogFmt(OP_SMOD, "Queued file upload: %s", filename);

	sfd->upload_list->push_back(ud);
	try_send_next_file(td);

	return 1;
}
示例#7
0
int
queue_get_file(THREAD_DATA *td, const char *filename, const char *initiator)
{
	THREAD_DATA::net_t::chunk_in_t *ci = td->net->chunk_i;

	if (strlen(filename) > 15) return 0;

	DOWNLOAD_ENTRY f;
	strlcpy(f.name, filename, 16);
	strlwr(f.name);
	strlcpy(f.initiator, initiator ? initiator : "", 24);
	ci->file_list->push_back(f);

	LogFmt(OP_SMOD, "Queued file download: %s", filename);

	try_get_next_file(td);

	return 1;
}
示例#8
0
void
try_send_next_file(THREAD_DATA *td)
{
	THREAD_DATA::net_t::send_file_data_t *sfd = td->net->send_file_data;

	if (sfd->in_use == 0 && !sfd->upload_list->empty()) {
		UPLOAD_DATA *ud = *sfd->upload_list->begin();

		sfd->in_use = 1;

		strlcpy(sfd->cur_initiator, ud->initiator, 64);
		strlcpy(sfd->cur_filename, ud->filename, 24);

		PubMessageFmt("*putfile %s", sfd->cur_filename);

		LogFmt(OP_SMOD, "Initiated file upload: %s", sfd->cur_filename);
		if (strlen(sfd->cur_initiator) > 0) {
			RmtMessageFmt(sfd->cur_initiator, "Initiated file upload: %s", sfd->cur_filename);
		}

		sfd->upload_list->erase(sfd->upload_list->begin());
		free(ud);
	} 
}
示例#9
0
static
void
mainloop(THREAD_DATA *td)
{
	THREAD_DATA::net_t *n = td->net;

	ticks_ms_t acc, ticks, lticks;	/* accumulator, current ticks, last iteration ticks */

	int	pktl;			/* packet length */
	uint8_t pkt[MAX_PACKET];	/* buffer space for a packet */

	if (connect_to_server(td) != 0) {
		free_thread_data(td);
		LogFmt(OP_MOD, "Error performing initial connect");
		return;
	}

	acc = 0;
	ticks = get_ticks_ms();
	lticks = ticks;
	ticks_ms_t last_botman_checkin = ticks;
	ticks_ms_t last_botman_stopcheck = ticks;
	ticks_ms_t last_config_mtime_check = ticks;
	while (td->running >= 0) {
		ticks = get_ticks_ms();
		acc += ticks - lticks;
		lticks = ticks;

		/* check in with the bot manager */
		if (ticks - last_botman_checkin >= BOTMAN_CHECKIN_INTERVAL) {
			botman_bot_checkin(td->botman_handle);
			last_botman_checkin = ticks;
		}
		if (ticks - last_botman_stopcheck >= BOTMAN_STOPCHECK_INTERVAL) {
			if (botman_bot_shouldstop(td->botman_handle)) {
				td->running = -1;
			}
			last_botman_stopcheck = ticks;
		}

		/* flush out tick events to bots */
		if (acc >= STEP_INTERVAL) { 
			libman_expire_timers(td);
			while(acc >= STEP_INTERVAL) {
				/* event_tick */
				libman_export_event(td, EVENT_TICK, NULL);
				acc -= STEP_INTERVAL;
			}
		}

		/* if the bot is disconnected, see if it is time to reconnect */
		if (n->state == NS_DISCONNECTED) {
			if (ticks - n->ticks->disconnected > 60000) {
				free_thread_data(td);
				init_thread_data(td);
				connect_to_server(td);
			} else {
				usleep(50000);	/* 50ms */
				continue;
			}
		}

		/* see if the config file has been modified and if so send a reread event */
		if (ticks - last_config_mtime_check >= CONFIG_MTIME_POLL_INTERVAL) {
			struct stat attr;
			memset(&attr, 0, sizeof(struct stat));
			if (stat(td->config->filename, &attr) == 0) {
				if (td->config->last_modified_time != attr.st_mtime) {
					libman_export_event(td, EVENT_CONFIG_CHANGE, NULL);
					td->config->last_modified_time = attr.st_mtime;
				}
			}
			last_config_mtime_check = ticks;
		}

		/* use up to STEP_INTERVAL ms for the db thread */
		ticks_ms_t ticks_taken = get_ticks_ms() - ticks;
		ticks_ms_t db_ticks = ticks_taken > STEP_INTERVAL ? STEP_INTERVAL : STEP_INTERVAL - ticks_taken;
		db_instance_export_events(db_ticks);

		/* read a packet or wait for a timeout */
		ticks_taken = get_ticks_ms() - ticks;
		ticks_ms_t timeout = ticks_taken > STEP_INTERVAL ? 0 : STEP_INTERVAL - ticks_taken;
		while (poll(n->pfd, 1, (int)timeout) > 0) {
			/* process incoming packet, data is waiting */
			pktl = (int)read(n->fd, pkt, MAX_PACKET);
			if (pktl >= 0) {
				++n->stats->packets_read;
				n->ticks->last_pkt_received = get_ticks_ms();

				if (n->encrypt->use_encryption) {
					if (pkt[0] == 0x00) {
						if (pktl >= 2) {
							decrypt_buffer(td, &pkt[2], pktl-2);
						}
					} else {
						decrypt_buffer(td, &pkt[1], pktl-1);
					}
				}

				if (td->debug->spew_packets) {
					spew_packet(pkt, pktl, DIR_INCOMING);
				}

				process_incoming_packet(td, pkt, pktl);
			}

			ticks_taken = get_ticks_ms() - ticks;
			timeout = timeout > ticks_taken ? timeout - ticks_taken : 0;
		}

		/* update the tick count after potential sleeping in poll() */
		ticks = get_ticks_ms();

		/* network state specfic actions */
		if (n->state == NS_CONNECTING) {
			/* retransmit connection request if it was lost */
			if (ticks - n->ticks->last_connection_request > 15000) {
				pkt_send_client_key(n->encrypt->client_key);
				n->ticks->last_connection_request = ticks;
			}
		} else if (ticks - n->ticks->last_pkt_received > 30*1000) {
			/* disconnect if no packets have been received for 30 seconds */
			Log(OP_MOD, "No data received for 30 seconds, reconnecting...");
			disconnect_from_server(td);
			continue;
		}

		/* transmit player position update if necessary */
		if (n->state == NS_CONNECTED && td->in_arena) {
			if ((ticks - n->ticks->last_pos_update_sent > 100
			    && td->bot_ship != SHIP_SPECTATOR)
			    || (ticks - n->ticks->last_pos_update_sent > 1000
			    && td->bot_ship == SHIP_SPECTATOR)) {
				pkt_send_position_update(td->bot_pos->x, td->bot_pos->y,
				    td->bot_vel->x, td->bot_vel->y);
				n->ticks->last_pos_update_sent = ticks;
			}
		}

		/* send periodic info/einfo */
		if (n->state == NS_CONNECTED) {
			// subtract 10000 to offset this by 10 seconds from *einfo to avoid filling buffers with commands/responses
			if (td->periodic->info && ticks - (td->periodic->last_info - 10000U) >= td->periodic->info) {
				int nhere = player_get_phere(td);
				PLAYER *parray = player_get_parray(td);
				for (int i = 0; i < nhere; ++i) {
					if (parray[i].here && td->enter->send_info) {
						PrivMessage(&parray[i], "*info");
					}
				}

				td->periodic->last_info = ticks;
			}

			if (td->periodic->einfo && ticks - td->periodic->last_einfo >= td->periodic->einfo) {
				int nhere = player_get_phere(td);
				PLAYER *parray = player_get_parray(td);
				for (int i = 0; i < nhere; ++i) {
					if (parray[i].here && td->enter->send_einfo) {
						PrivMessage(&parray[i], "*einfo");
					}
				}

				td->periodic->last_einfo = ticks;
			}
		}

		/* retransmit reliable packets that have not been acked */
		rpacket_list_t *l = n->rel_o->queue;
		rpacket_list_t::iterator iter = l->begin();
		while (iter != l->end()) {
			RPACKET *rp = *iter;
			if (ticks - rp->ticks > RELIABLE_RETRANSMIT_INTERVAL) {
				PACKET *p = allocate_packet(rp->len);
				memcpy(p->data, rp->data, rp->len);

				/* update packets retransmit tick */
				rp->ticks = ticks;

				queue_packet(p, SP_HIGH);
			}
			
			++iter;
		}

		/* free absent players if its time */
		ticks_ms_t flush_check_interval = 60 * 60 * 1000;
		if (ticks - td->arena->ticks->last_player_flush > flush_check_interval) {
			player_free_absent_players(td, flush_check_interval, true);
			td->arena->ticks->last_player_flush = ticks;
		}

		/* write packets generated during loop iteration */
		send_outgoing_packets(td);
	} /* while td->running != 0 */
}
示例#10
0
void
do_send_file(THREAD_DATA *td)
{
	THREAD_DATA::net_t::send_file_data_t *sfd = td->net->send_file_data;
	char *filename = sfd->cur_filename;
	const char *initiator = (strlen(sfd->cur_initiator) > 0) ? sfd->cur_initiator : NULL;

	char full_filename[64];

	snprintf(full_filename, 64, "files/%s", filename);

	initiator = initiator ? initiator : "";

	FILE *f = fopen(full_filename, "rb");
	if (f == NULL) {
		LogFmt(OP_SMOD, "Couldn't open file for sending: %s", filename);
		if (initiator) {
			RmtMessageFmt(initiator, "Couldn't open file for sending: %s", filename);
		}
		sfd->in_use = 0;
		return;
	}

	struct stat s;
	memset(&s, 0, sizeof(s));
	fstat(fileno(f), &s);
	int bufl = s.st_size + 17;
	uint8_t *buf = (uint8_t*)xmalloc(bufl);
	if (fread(&buf[17], bufl - 17, 1, f) != 1) {
		LogFmt(OP_SMOD, "Couldn't read file for sending: %s", filename);
		if (initiator) {
			RmtMessageFmt(initiator, "Couldn't read file for sending: %s", filename);
		}
		fclose(f);
		free(buf);
		sfd->in_use = 0;
		return;
	}

	/* add file transfer header */
	buf[0] = 0x16;
	strlcpy((char*)&buf[1], filename, 16);

	int bytes_left = bufl;

	/* send initial stream start */
	while (bytes_left > 0) {
		int nout = MIN(bytes_left, 220); // must fit into a cluster header
		PACKET *p = allocate_packet(6 + nout);
		build_packet(p->data, "AACZ",
		    0x00,
		    0x0A,
		    bufl,
		    &buf[bufl - bytes_left], nout);
		bytes_left -= nout;

		queue_packet_reliable(p, SP_DEFERRED);
	}

	free(buf);
}
示例#11
0
/*
 * Spawns the initial bot process and waits for them all to exit.
 */
int
main(int argc, char *argv[])
{
	char *pythonpath = getenv("PYTHONPATH");
	if (pythonpath) {
		char *str = (char*)xzmalloc(strlen(pythonpath) + strlen(":") + strlen("./libs") + 1);
		sprintf(str, "%s:%s", "./libs", pythonpath);
		setenv("PYTHONPATH", str, 1);
		free(str);
	} else {
		setenv("PYTHONPATH", "./libs", 1);
	}
	Py_Initialize();
	init_opencore();
	PyObject *sysPath = PySys_GetObject("path");
	PyObject *libDir = PyString_FromString(".");
	PyList_Append(sysPath, libDir);
	Py_DECREF(libDir);

	if (pthread_key_create(&g_tls_key, NULL) != 0) {
		Log(OP_SMOD, "Error creating thread-specific storage");
		exit(-1);
	}
	pthread_setspecific(g_tls_key, NULL);

	/* make directories */
	mkdir("files", 0700);

	/* setup packet handlers */
	for (int i = 0; i < 256; ++i) {
		g_pkt_core_handlers[i] = null_handler;
		g_pkt_game_handlers[i] = null_handler;
	}

	g_pkt_core_handlers[0x02] = pkt_handle_core_0x02;
	g_pkt_core_handlers[0x03] = pkt_handle_core_0x03;
	g_pkt_core_handlers[0x04] = pkt_handle_core_0x04;
	g_pkt_core_handlers[0x05] = pkt_handle_core_0x05;
	g_pkt_core_handlers[0x06] = pkt_handle_core_0x06;
	g_pkt_core_handlers[0x07] = pkt_handle_core_0x07;
	g_pkt_core_handlers[0x08] = pkt_handle_core_0x08_0x09;
	g_pkt_core_handlers[0x09] = pkt_handle_core_0x08_0x09;
	g_pkt_core_handlers[0x0A] = pkt_handle_core_0x0A;
	g_pkt_core_handlers[0x0E] = pkt_handle_core_0x0E;

	g_pkt_game_handlers[0x02] = pkt_handle_game_0x02;
	g_pkt_game_handlers[0x03] = pkt_handle_game_0x03;
	g_pkt_game_handlers[0x04] = pkt_handle_game_0x04;
	g_pkt_game_handlers[0x07] = pkt_handle_game_0x07;
	g_pkt_game_handlers[0x06] = pkt_handle_game_0x06;
	g_pkt_game_handlers[0x0A] = pkt_handle_game_0x0A;
	g_pkt_game_handlers[0x0D] = pkt_handle_game_0x0D;
	g_pkt_game_handlers[0x0E] = pkt_handle_game_0x0E;
	g_pkt_game_handlers[0x14] = pkt_handle_game_0x14;
	g_pkt_game_handlers[0x19] = pkt_handle_game_0x19;
	g_pkt_game_handlers[0x1C] = pkt_handle_game_0x1C;
	g_pkt_game_handlers[0x1D] = pkt_handle_game_0x1D;
	g_pkt_game_handlers[0x27] = pkt_handle_game_0x27;
	g_pkt_game_handlers[0x28] = pkt_handle_game_0x28;
	g_pkt_game_handlers[0x29] = pkt_handle_game_0x29;
	g_pkt_game_handlers[0x2E] = pkt_handle_game_0x2E;
	g_pkt_game_handlers[0x2F] = pkt_handle_game_0x2F;
	g_pkt_game_handlers[0x31] = pkt_handle_game_0x31;

	struct utsname uts;
	bzero(&uts, sizeof(struct utsname));
	uname(&uts);
	uint64_t hash = hash_buf(&uts, sizeof(struct utsname));
	g_machineid = gen_valid_mid(hash & 0xFFFFFFFF);
	g_permissionid = hash >> 32;

	load_op_file();

	static const char* const masterconfig = "types/master.conf";

	log_init();
	db_init(masterconfig);
	botman_init();

	/* run the master bot */
	char arenaname[32] = { '\0' };
	config_get_string("login.masterarena", arenaname, sizeof(arenaname), "#master", masterconfig);
	LogFmt(OP_MOD, "Starting master into %s", arenaname);
	char *err = StartBot("master", arenaname, NULL);
	if (err) {
		LogFmt(OP_MOD, "Error starting master bot: %s", err);
		return -1;
	}

	/* become the bot management thread and loop */
	botman_mainloop();

	botman_shutdown();
	db_shutdown();
	log_shutdown();

	pthread_key_delete(g_tls_key);

	Py_Finalize();

	return 0;
}