Created
January 20, 2013 06:36
-
-
Save hank/4576989 to your computer and use it in GitHub Desktop.
A little program I wrote for a class.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Project: Module 12 Assignment | |
* | |
* Program: control_probe | |
* File Name: control_probe.c | |
* Purpose: Connect to a shared memory area and a probe guidance server, and | |
* command a probe to map the given cavern using simple network commands. The | |
* algorithm at work uses a recursive depth-first search, which uses a fair | |
* bit of memory for the stack, but usually solves a cavern in 10-13 seconds | |
* on aplcenmp, and doesn't invoke a single lawsuit in the first 50 caverns | |
* tested. | |
* | |
* Synopsis (Usage and Parameters): | |
* ./control_probe -m <shared memory key> [-P <server port> -c <cavern id>] | |
* The port and cavern ID are optional, and are 10000 and 0 respectively by | |
* default. | |
* | |
* Programmer: Erik Gregg | |
* Organization: JHU EP | |
* Host System: UNIX | |
* Language: C | |
* Date Created: 2012/12/10 | |
*/ | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <signal.h> | |
#include "log_mgr.h" | |
#include "shmlib.h" | |
#include "socket_utils.h" | |
#include "cavern.h" | |
#define ROWS_SIZE 24 | |
#define COLS_SIZE 80 | |
#define SHM_SIZE (2 * ROWS_SIZE * 2 * COLS_SIZE) | |
#define CENTER (SHM_SIZE / 2) | |
#define POS_NORTH (position - 2*COLS_SIZE) | |
#define POS_EAST (position - 1) | |
#define POS_WEST (position + 1) | |
#define POS_SOUTH (position + 2*COLS_SIZE) | |
/* Default Cavern. 0 for random */ | |
#define CAVERN 0 | |
/* Default server port. */ | |
#define SERVER_PORT 10000 | |
/* typedefs */ | |
typedef char MAPS [2*ROWS_SIZE][2*COLS_SIZE]; | |
/* Globals */ | |
MAPS *Display_map; | |
static int Move_count = 0; | |
static int Shm_key = 0; | |
/* Function Declarations */ | |
static int insert_probe(int, int); | |
static int move_probe(int, DIRECTIONS); | |
static int explode_probe(int, time_t); | |
static int print_results(PROBE_MESSAGES*); | |
static int print_move_response(PROBE_MESSAGES*); | |
int probe_explore_recurse(int, char*); | |
int probe_explore(int, char*, int); | |
/* signal handler */ | |
void handler(int dum) | |
{ | |
/* Delete the shared memory */ | |
destroy_shm(Shm_key); | |
exit(100); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
extern int opterr; /* used by getopt(3) */ | |
extern char *optarg; /* used by getopt(3) */ | |
char c; | |
int shmid; | |
int port = SERVER_PORT; | |
int cavern = CAVERN; | |
int sock; | |
int status; | |
char* shm; | |
time_t start_time, end_time; | |
/* set up signal handling */ | |
signal(SIGINT, handler); | |
signal(SIGQUIT, handler); | |
/* command line option argument processing */ | |
opterr = 0; /* suppress getopt(3) generated messages */ | |
while ((c = getopt(argc, argv, "m:P:c:")) != EOF) | |
switch (c) | |
{ | |
case 'm': | |
Shm_key = atoi(optarg); | |
break; | |
case 'P': | |
port = atoi(optarg); | |
break; | |
case 'c': | |
cavern = atoi(optarg); | |
break; | |
default: | |
break; | |
} | |
if (Shm_key <= 0) | |
{ | |
fprintf (stderr, "%s -m <shm_key> -P <port> -c <cavern>\n", argv[0]); | |
exit (1); | |
} | |
// Connect to shared memory | |
shm = connect_shm(Shm_key, SHM_SIZE); | |
if(!shm) | |
{ | |
log_event(FATAL, "connect_shm() failed"); | |
fprintf(stderr, "connect_shm() failed\n"); | |
exit(-1); | |
} | |
log_event(INFO, "connect_shm(%x, %d) success", Shm_key, SHM_SIZE); | |
/* Connect to stream socket */ | |
sock = setup_client(port); | |
if(sock < 0) | |
{ | |
fprintf(stderr, "socket creation failed\n"); | |
log_event(FATAL, "socket creation failed"); | |
exit (3); | |
} | |
log_event(INFO, "setup_client(%d) success", port); | |
/* Insert the probe. */ | |
if(insert_probe(sock, cavern) < 0) | |
{ | |
fprintf(stderr, "Insert probe failed.\n"); | |
log_event(FATAL, "Insert probe failed"); | |
exit (3); | |
} | |
/* Record the start time */ | |
start_time = time(0); | |
/* Move the probe. */ | |
probe_explore_recurse(sock, shm); | |
/* Record the end time */ | |
end_time = time(0); | |
/* Explode the probe. */ | |
if(explode_probe(sock, end_time - start_time) < 0) | |
{ | |
fprintf(stderr, "Explode probe failed.\n"); | |
log_event(FATAL, "Explode probe failed"); | |
exit (3); | |
} | |
/* Kill the display */ | |
shm[CENTER] = ')'; | |
/* Delete the shared memory */ | |
destroy_shm(Shm_key); | |
/* Close the socket */ | |
close(sock); | |
exit(0); | |
} | |
static int insert_probe(int sock, int cavern) | |
{ | |
PROBE_MESSAGES pm = {0}; | |
pm.msg_type = MSG_INSERT_PROBE; | |
pm.msg.insert.cavern = cavern; | |
send(sock, &pm, sizeof(pm), 0); | |
return OK; | |
} | |
static int move_probe(int sock, DIRECTIONS dir) | |
{ | |
PROBE_MESSAGES pm = {0}; | |
pm.msg_type = MSG_MOVE; | |
pm.msg.move.move = dir; | |
send(sock, &pm, sizeof(pm), 0); | |
recv(sock, &pm, sizeof(pm), 0); | |
// Could get MSG_MV_RESPONSE or MSG_RESULTS | |
// MSG_RESULTS will happen if 5000 moves or 30 minutes are used. | |
if(pm.msg_type == MSG_MV_RESPONSE) | |
{ | |
print_move_response(&pm); | |
return pm.msg.mv_response.success; | |
} | |
else | |
{ | |
print_results(&pm); | |
return ERROR; | |
} | |
} | |
static int explode_probe(int sock, time_t elapsed) | |
{ | |
PROBE_MESSAGES pm = {0}; | |
pm.msg_type = MSG_EXPLODE; | |
send(sock, &pm, sizeof(pm), 0); | |
recv(sock, &pm, sizeof(pm), 0); | |
printf("Probe Exploded after %d seconds\n", elapsed); | |
log_event(INFO, "Probe Exploded after %d seconds", elapsed); | |
if(print_results(&pm) == OK) return OK; | |
else return ERROR; | |
} | |
static int print_results(PROBE_MESSAGES* pm) | |
{ | |
if(pm->msg_type == MSG_RESULTS) | |
{ | |
printf("Cavern Size: %d\n" | |
"Amount Mapped: %d\n" | |
"Lawsuits: %d\n" | |
"Moves: %d\n" | |
"Move per space ratio: %.3f\n", | |
pm->msg.results.cavern_size, | |
pm->msg.results.amt_mapped, | |
pm->msg.results.lawsuits, | |
pm->msg.results.moves, | |
((float)pm->msg.results.moves)/pm->msg.results.cavern_size | |
); | |
return OK; | |
} | |
else | |
{ | |
log_event(WARNING, "print_results called on non-results"); | |
return ERROR; | |
} | |
} | |
static int print_move_response(PROBE_MESSAGES* pm) | |
{ | |
if(pm->msg_type == MSG_MV_RESPONSE) | |
{ | |
return OK; | |
} | |
else | |
{ | |
log_event(WARNING, "print_move_response called on wrong message type"); | |
return ERROR; | |
} | |
} | |
int probe_explore_recurse(int sock, char* shm) | |
{ | |
// Initialize state | |
int position = CENTER; | |
probe_explore(sock, shm, position); | |
} | |
#define PROBE_EXPLORE(comp, bound, pos_dir, move_dir, move_opposite, str_dir) \ | |
if(position comp bound) \ | |
{ \ | |
if(shm[pos_dir] == 0) \ | |
{ \ | |
printf("%d moves\r", ++Move_count); \ | |
status = move_probe(sock, move_dir); \ | |
if(status == YES) \ | |
{ \ | |
log_event(INFO, "Successfully moved " str_dir "!"); \ | |
status = probe_explore(sock, shm, pos_dir); \ | |
if(status == ERROR) \ | |
{ \ | |
return ERROR; \ | |
} \ | |
printf("%d moves\r", ++Move_count); \ | |
if(move_probe(sock, move_opposite) == ERROR) \ | |
{ \ | |
return ERROR; \ | |
} \ | |
} \ | |
else if(status == NO) \ | |
{ \ | |
log_event(INFO, "Failed to move " str_dir "!"); \ | |
shm[pos_dir] = '#'; \ | |
} \ | |
else \ | |
{ \ | |
return ERROR; \ | |
} \ | |
} \ | |
} | |
int probe_explore(int sock, char* shm, int position) | |
{ | |
int status; | |
log_event(INFO, "At position %d", position); | |
shm[position] = '.'; | |
// First, try to move the probe north if it's possible | |
PROBE_EXPLORE(>=, 2*COLS_SIZE, POS_NORTH, MOVE_NORTH, MOVE_SOUTH, "north"); | |
// Try to move the probe east if it's possible | |
PROBE_EXPLORE(>, 0, POS_EAST, MOVE_EAST, MOVE_WEST, "east"); | |
// Try to move the probe south if it's possible | |
PROBE_EXPLORE(<=, SHM_SIZE - 2*COLS_SIZE - 1, POS_SOUTH, MOVE_SOUTH, MOVE_NORTH, "south"); | |
// Try to move the probe west if it's possible | |
PROBE_EXPLORE(<, SHM_SIZE - 1, POS_WEST, MOVE_WEST, MOVE_EAST, "west"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment