📄 client.c
字号:
/* -*- Mode: C -*- *//* client.C * CMUnited98 (soccer client for Robocup98) * Peter Stone <pstone@cs.cmu.edu> * Computer Science Department * Carnegie Mellon University * Copyright (C) 1998 Peter Stone * * CMUnited-98 was created by Peter Stone, Manuela Veloso, and Patrick Riley * * You may copy and distribute this program freely as long as you retain this notice. * If you make any changes or have any comments we would appreciate a message. *//* client.C contains the main program loop * It is partially based on Player.C from the turnballclient of Alessandro Bissacco */#include "client.h"#include "types.h"#include "netif.h"#include "Memory.h"#include "parse.h"#include "utils.h"#include "behave.h"void send_initialize_message();void parse_initialize_message(char *);Bool wait_for_signals(sigset_t *);sigset_t init_handler();void sigio_handler(); void sigalrm_handler();void send_action();void resend_last_action();/* Global variables -- don't want to reallocate buffers each time */sigset_t sigiomask, sigalrmask;//Memory Global_Mem;//Memory *const Mem = &Global_Mem;Memory *Mem;char recvbuf[MAXMESG]; char sendbuf[MAXMESG]; char *GLOBAL_sense_body_message = "(sense_body)";int alrsigs_since_iosig=0;/****************************************************************************************/main(int argc, char *argv[]){ Mem = new Memory(); if ( Mem == NULL ){ my_error("couldn't allocate Mem"); exit(0); } Mem->GetOptions(argc,argv); Socket sock = init_connection(Mem->SP_host,Mem->SP_port); Mem->sock = &sock; if(Mem->sock->socketfd == -1) { cerr << "Can't open connection for player" << endl; abort(); } send_initialize_message(); wait_message(recvbuf, Mem->sock); parse_initialize_message(recvbuf); Mem->Initialize(); sigset_t sigfullmask = init_handler(); while ( Mem->ServerAlive == TRUE && wait_for_signals(&sigfullmask) ); if (Mem->sock->socketfd != -1) close_connection(Mem->sock); printf("Shutting down player %d\n",Mem->MyNumber);}/****************************************************************************************//****************************************************************************************//****************************************************************************************//* Send initialize message */void send_initialize_message(){ if (Mem->IP_reconnect) sprintf(sendbuf, "(reconnect %s %d)", Mem->MyTeamName, Mem->IP_reconnect); else if ( Mem->CP_goalie == TRUE && Mem->SP_version >= 4.00){ sprintf(sendbuf, "(init %s (version %.2f) (goalie))", Mem->MyTeamName, Mem->SP_version); } else sprintf(sendbuf, "(init %s (version %.2f))", Mem->MyTeamName, Mem->SP_version); if(send_message(sendbuf, Mem->sock) == -1) abort(); }/****************************************************************************************//* Parse initialize message */void parse_initialize_message(char *recvbuf){ char mode[100]; if ( !(strncmp(recvbuf,"(init",4)) ) { /* It's an init msg */ sscanf(recvbuf,"(init %c %d %[^)]",&Mem->MySide, &Mem->MyNumber, mode); Mem->ServerAlive = TRUE; } else if ( !(strncmp(recvbuf,"(reconnect",4)) ) { /* It's a reconnect msg */ sscanf(recvbuf,"(reconnect %c %[^)]",&Mem->MySide, mode); Mem->MyNumber = Mem->IP_reconnect; printf("reconnecting to %d on side %c!\n",Mem->MyNumber,Mem->MySide); Mem->ServerAlive = TRUE; } else Mem->ServerAlive = FALSE; if ( Mem->CP_goalie && Mem->FP_goalie_number != Mem->MyNumber ) my_error("goalie number inconsistent with me being goalie"); if ( !Mem->CP_goalie && Mem->FP_goalie_number == Mem->MyNumber ) my_error("I should be the goalie"); if ( mode[0] == 'b' ){ /* Before_kick_off */ Mem->SetPlayMode(PM_Before_Kick_Off); if ( Mem->MySide == 'l' ) Mem->KickOffMode = KO_Mine; else Mem->KickOffMode = KO_Theirs; } else /* Act as if the game's in progress */ Mem->SetPlayMode(PM_Play_On); printf( "------------------------------------------------------------------------\n"); printf( "Connected player %d on team %s\n",Mem->MyNumber,Mem->MyTeamName); printf( "------------------------------------------------------------------------\n"); printf( "CMUnited98 was created by Peter Stone, Manuela Veloso, and Patrick Riley\n"); printf( "Copyright 1998. All rights reserved.\n"); printf( "------------------------------------------------------------------------\n\n"); }/****************************************************************************************//****************************************************************************************//****************************************************************************************//* set time interval between the sensor receiving and command sending */ inline void set_timer() { struct itimerval itv; itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = Mem->TimerInterval * 1000; itv.it_value.tv_sec = 0; itv.it_value.tv_usec = Mem->TimerInterval * 1000; setitimer(ITIMER_REAL, &itv, NULL);}inline void set_timer(int usec) { struct itimerval itv; itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = Mem->TimerInterval * 1000; itv.it_value.tv_sec = 0; itv.it_value.tv_usec = usec; setitimer(ITIMER_REAL, &itv, NULL);}/****************************************************************************************/sigset_t init_handler() { sigemptyset(&sigalrmask); sigaddset(&sigalrmask, SIGALRM); sigemptyset(&sigiomask); sigaddset(&sigiomask, SIGIO); struct sigaction sigact; sigact.sa_flags = 0; sigact.sa_mask = sigiomask;#ifdef Solaris sigact.sa_handler = (void (*)(int))sigalrm_handler; #else sigact.sa_handler = (void (*)(int))sigalrm_handler; #endif sigaction(SIGALRM, &sigact, NULL); sigact.sa_mask = sigalrmask;#ifdef Solaris sigact.sa_handler = (void (*)(int))sigio_handler; #else sigact.sa_handler = (void (*)(int))sigio_handler; #endif sigaction(SIGIO, &sigact, NULL); set_timer(); sigprocmask(SIG_UNBLOCK, &sigiomask, NULL); sigprocmask(SIG_UNBLOCK, &sigalrmask, NULL); sigset_t sigsetmask; sigprocmask(SIG_BLOCK, NULL, &sigsetmask); /* Get's the currently unblocked signals */ return sigsetmask; }/****************************************************************************************//* suspend the process until one of the signals comes through *//* could check for situation to kill client, return FALSE *//* i.e. too many actions with no sensory input coming in */Bool wait_for_signals(sigset_t *mask){ sigsuspend(mask); return TRUE;}/****************************************************************************************//* SIGIO handler: receive and parse messages from server */void sigio_handler() { sigprocmask(SIG_BLOCK, &sigalrmask, NULL); int counter = 0; Time StartTime = Mem->CurrentTime; while (receive_message(recvbuf, Mem->sock) == 1) { Parse(recvbuf); counter++; } if ( Mem->CurrentTime - StartTime > 1 && StartTime.s == 0 && Mem->CurrentTime.s == 0 ) my_error("Received several steps at once -- missing action ops!!! (%d %d)", StartTime.t,StartTime.s); sigprocmask(SIG_UNBLOCK, &sigalrmask, NULL); alrsigs_since_iosig=0; // if (counter>1) printf("Got %d messages\n",counter);}/****************************************************************************************//* SIGALRM handler: send something to the server */void sigalrm_handler() { sigprocmask(SIG_BLOCK, &sigiomask, NULL); if (Mem->ClockStopped) Mem->StoppedClockMSec += Mem->TimerInterval; if (alrsigs_since_iosig++ > 40) Mem->ServerAlive = FALSE; else if ( Mem->CurrentTime > Mem->LastActionOpTime ){ if ( Mem->CurrentTime-1 != Mem->LastActionOpTime && Mem->LastActionOpTime != 0 ) my_error("Missed a cycle!! (%d %d)",Mem->LastActionOpTime.t,Mem->LastActionOpTime.s); if ( Mem->NewSight ) Mem->FirstActionOpSinceLastSight = TRUE; Mem->update(); behave(); Mem->LastActionOpTime = Mem->CurrentTime; Mem->FirstActionOpSinceLastSight = FALSE; } if ( Mem->Action->valid() ) { send_action(); } else if ( Mem->ResendNeeded() ){ resend_last_action(); }#ifndef RELEASE_VERSION else if ( Mem->Communicate() ){ send_message( Mem->SayBuffer(), Mem->sock ); } #endif else if ( Mem->ChangeView.valid() ){ if ( Mem->ChangeView.time < Mem->CurrentTime-1 ) my_error("old change_view"); send_message( Mem->ChangeView.command, Mem->sock ); Mem->ChangeView.type = CMD_none; /* so it's no longer valid */ } else { send_message(GLOBAL_sense_body_message,Mem->sock); } sigprocmask(SIG_UNBLOCK, &sigiomask, NULL); }/****************************************************************************************//****************************************************************************************//****************************************************************************************//* insert turn/dash/kick commands in commandlist */void turn(AngleDeg ang) { NormalizeAngleDeg(&ang); /* turn so that the actual turn is the desired turn */ /* pos.rotate( ang/(1.0 + SP_inertia_moment * MySpeed()) ); */ if ( Mem->MyVelConf() ) ang *= (1 + Mem->SP_inertia_moment * Mem->MySpeed()); if ( ang > Mem->SP_max_moment ) ang = Mem->SP_max_moment; if ( ang < Mem->SP_min_moment ) ang = Mem->SP_min_moment; if (ang < .1 && ang > -.1) { Mem->Action->type = CMD_none; return; /* No turn */ } Mem->Action->type = CMD_turn; Mem->Action->power = 0; Mem->Action->angle = ang; Mem->Action->time = Mem->CurrentTime; sprintf(Mem->Action->command,"(turn %.2f)", ang);} /****************************************************************************************/void dash(float power) { if ( Mem->PlayMode == PM_Before_Kick_Off ) return; if (power > Mem->SP_max_power) my_error("Can't dash that fast: %.1f",power); if (power < Mem->SP_min_power) my_error("Can't dash that 'slow': %.1f",power); /* Factor for stamina--don't dash more than stamina or more than necessary to get you to max speed */ Mem->VerifyDash(&power); if (fabs(power) < 1){ Mem->Action->type = CMD_none; return; /* No dash */ } Mem->Action->type = CMD_dash; Mem->Action->power = power; Mem->Action->angle = 0; Mem->Action->time = Mem->CurrentTime; sprintf(Mem->Action->command, "(dash %.2f)", power);}/****************************************************************************************/void kick(float power, AngleDeg dir) { if ( !(Mem->BallKickable()) ) my_error("Can't kick a ball that's too far away"); if ( Mem->PlayMode == PM_Before_Kick_Off ) return; if (power > Mem->SP_max_power) my_error("Can't kick that hard"); if (power < 0 ) my_error("Can't kick < 0"); NormalizeAngleDeg(&dir); Mem->Action->type = CMD_kick; Mem->Action->power = power; Mem->Action->angle = dir; Mem->Action->time = Mem->CurrentTime; sprintf(Mem->Action->command, "(kick %.2f %.2f)", power, dir);}/****************************************************************************************/void goalie_catch(AngleDeg dir) { if ( !(Mem->BallCatchable()) ) my_error("Can't catch a ball that's too far away"); if ( !Mem->CP_goalie ) my_error("Only goalies can catch"); if ( Mem->PlayMode == PM_Before_Kick_Off ) return; NormalizeAngleDeg(&dir); Mem->Action->type = CMD_catch; Mem->Action->power = 0; Mem->Action->angle = dir; Mem->Action->time = Mem->CurrentTime; sprintf(Mem->Action->command, "(catch %.2f)", dir);}/****************************************************************************************/void move(float x, float y) { if ( Mem->PlayMode != PM_Before_Kick_Off ) my_error("Can only move in before kickoff mode"); /* Perhaps here convert to a position on the field */ if ( fabs(y) > Mem->SP_pitch_width/2 || x > 0 || x < -Mem->SP_pitch_length/2 ) my_error("Must move to a place on the pitch"); Mem->Action->type = CMD_move; Mem->Action->x = x; Mem->Action->y = y; Mem->Action->time = Mem->CurrentTime; sprintf(Mem->Action->command, "(move %.2f %.2f)", x, y);}/****************************************************************************************/void disconnect(){ Mem->Action->type = CMD_bye; Mem->Action->time = Mem->CurrentTime; sprintf(Mem->Action->command, "(bye)");}/****************************************************************************************/void change_view(Vqual qual, Vwidth width) { if ( qual==Mem->ViewQuality && width==Mem->ViewWidth ) return; /* my_error("Nothing to change about view"); */ Mem->ChangeView.type = CMD_change_view; Mem->ChangeView.qual = qual; Mem->ChangeView.width = width; Mem->ChangeView.time = Mem->CurrentTime; char qual_string[10], width_string[10]; switch (qual){ case VQ_High: sprintf(qual_string,"high"); break; case VQ_Low: sprintf(qual_string,"low"); break; } switch (width){ case VW_Narrow: sprintf(width_string,"narrow"); break; case VW_Normal: sprintf(width_string,"normal"); break; case VW_Wide: sprintf(width_string,"wide"); break; } sprintf(Mem->ChangeView.command, "(change_view %s %s)", width_string, qual_string);}/****************************************************************************************/void send_action(){ if ( !(Mem->Action->valid(Mem->CurrentTime)) ) my_error("Old action %d %d",Mem->Action->time.t,Mem->Action->time.s); send_message(Mem->Action->command, Mem->sock); switch (Mem->Action->type){ case CMD_kick: Mem->kicks++; break; case CMD_dash: Mem->dashes++; break; case CMD_turn: Mem->turns++; break; default: ; } Command *tmp = Mem->LastAction; Mem->LastAction = Mem->Action; Mem->Action = tmp; Mem->Action->type = CMD_none; /* So it's invalid */ Mem->NewAction = TRUE;}/****************************************************************************************/void resend_last_action(){ if ( Mem->LastActionType() == Mem->ResendType ){ my_stamp; printf("resending\n"); send_message(Mem->LastAction->command, Mem->sock); switch (Mem->LastActionType()){ case CMD_kick: Mem->kicks++; break; case CMD_dash: Mem->dashes++; break; case CMD_turn: Mem->turns++; break; default: ; } } else my_error("last action isn't a %d",Mem->ResendType); Mem->RequestResend = FALSE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -