void Execute() { if (CurrentVote.Voting) { Player->PrintToClient(PRINT_HIGH, "Vote already in progress."); return; } if (ArgCount() != 3) { Player->PrintToClient (PRINT_HIGH, "Syntax: vote nextmap mapname\n"); return; } CVoteMapData *voteData = QNew(TAG_GENERIC) CVoteMapData(true, ArgGets(2)); CurrentVote.StartVote(VOTE_NEXTMAP, voteData, Player->Client.Persistent.Name); }
/** * ArgRejoinArray * * "Rejoins" arguments in an array. * * @param ArgV the array * @param Index the index of the first argument which is to be rejoined */ void ArgRejoinArray(const char **ArgV, int Index) { int Count = ArgCount(ArgV[0]); if (Count - 1 <= Index) { return; } for (int i = Index + 1; i < Count; i++) { char *Arg = const_cast<char *>(ArgV[i]); if (strchr(Arg, ' ') != NULL || *(Arg - 1) == ':') { *(Arg - 1) = ':'; *(Arg - 2) = ' '; } else { *(Arg - 1) = ' '; } } }
/** * ParseLineArgV * * Parses and processes a line which was sent by the server. * * @param argc number of tokens * @param argv the tokens */ bool CIRCConnection::ParseLineArgV(int argc, const char **argv) { CChannel *Channel; CClientConnection *Client; m_LastResponse = g_CurrentTime; if (argc < 2) { return true; } const char *Reply = argv[0]; const char *Raw = argv[1]; char *Nick = ::NickFromHostmask(Reply); int iRaw = atoi(Raw); bool b_Me = false; if (m_CurrentNick != NULL && Nick != NULL && strcasecmp(Nick, m_CurrentNick) == 0) { b_Me = true; } free(Nick); Client = GetOwner()->GetClientConnectionMultiplexer(); // HASH values CHashCompare hashRaw(argv[1]); static CHashCompare hashPrivmsg("PRIVMSG"); static CHashCompare hashNotice("NOTICE"); static CHashCompare hashJoin("JOIN"); static CHashCompare hashPart("PART"); static CHashCompare hashKick("KICK"); static CHashCompare hashNick("NICK"); static CHashCompare hashQuit("QUIT"); static CHashCompare hashMode("MODE"); static CHashCompare hashTopic("TOPIC"); static CHashCompare hashPong("PONG"); // END of HASH values if (argc > 3 && iRaw == 433) { bool ReturnValue = ModuleEvent(argc, argv); if (ReturnValue) { if (GetCurrentNick() == NULL) { WriteLine("NICK :%s_", argv[3]); } if (m_NickCatchTimer == NULL) { m_NickCatchTimer = new CTimer(30, false, NickCatchTimer, this); } } return ReturnValue; } else if (argc > 3 && hashRaw == hashPrivmsg && Client == NULL) { const char *Host; const char *Dest = argv[2]; char *Nick = ::NickFromHostmask(Reply); Channel = GetChannel(Dest); if (Channel != NULL) { CNick *User = Channel->GetNames()->Get(Nick); if (User != NULL) { User->SetIdleSince(g_CurrentTime); } Channel->AddBacklogLine(argv[0], argv[3]); } if (!ModuleEvent(argc, argv)) { free(Nick); return false; } /* don't log ctcp requests */ if (argv[3][0] != '\1' && argv[3][strlen(argv[3]) - 1] != '\1' && Dest != NULL && Nick != NULL && m_CurrentNick != NULL && strcasecmp(Dest, m_CurrentNick) == 0 && strcasecmp(Nick, m_CurrentNick) != 0) { char *Dup; char *Delim; Dup = strdup(Reply); if (AllocFailed(Dup)) { free(Nick); return true; } Delim = strchr(Dup, '!'); if (Delim != NULL) { *Delim = '\0'; Host = Delim + 1; } GetOwner()->Log("%s (%s): %s", Dup, Delim ? Host : "<unknown host>", argv[3]); free(Dup); } free(Nick); UpdateHostHelper(Reply); return true; } else if (argc > 3 && hashRaw == hashPrivmsg && Client != NULL) { Channel = GetChannel(argv[2]); if (Channel != NULL) { Channel->AddBacklogLine(argv[0], argv[3]); } } else if (argc > 3 && hashRaw == hashNotice && Client == NULL) { const char *Dest = argv[2]; char *Nick; if (!ModuleEvent(argc, argv)) { return false; } Nick = ::NickFromHostmask(Reply); /* don't log ctcp replies */ if (argv[3][0] != '\1' && argv[3][strlen(argv[3]) - 1] != '\1' && Dest != NULL && Nick != NULL && m_CurrentNick != NULL && strcasecmp(Dest, m_CurrentNick) == 0 && strcasecmp(Nick, m_CurrentNick) != 0) { GetOwner()->Log("%s (notice): %s", Reply, argv[3]); } free(Nick); return true; } else if (argc > 2 && hashRaw == hashJoin) { if (b_Me) { AddChannel(argv[2]); /* GetOwner() can be NULL if AddChannel failed */ if (GetOwner() != NULL && Client == NULL) { WriteLine("MODE %s", argv[2]); } } Channel = GetChannel(argv[2]); if (Channel != NULL) { Nick = NickFromHostmask(Reply); if (AllocFailed(Nick)) { return false; } Channel->AddUser(Nick, '\0'); free(Nick); } UpdateHostHelper(Reply); } else if (argc > 2 && hashRaw == hashPart) { bool bRet = ModuleEvent(argc, argv); if (b_Me) { RemoveChannel(argv[2]); } else { Channel = GetChannel(argv[2]); if (Channel != NULL) { Nick = ::NickFromHostmask(Reply); if (AllocFailed(Nick)) { return false; } Channel->RemoveUser(Nick); free(Nick); } } UpdateHostHelper(Reply); return bRet; } else if (argc > 3 && hashRaw == hashKick) { bool bRet = ModuleEvent(argc, argv); if (m_CurrentNick != NULL && strcasecmp(argv[3], m_CurrentNick) == 0) { RemoveChannel(argv[2]); if (Client == NULL) { char *Dup = strdup(Reply); if (AllocFailed(Dup)) { return bRet; } char *Delim = strchr(Dup, '!'); const char *Host = NULL; if (Delim) { *Delim = '\0'; Host = Delim + 1; } GetOwner()->Log("%s (%s) kicked you from %s (%s)", Dup, Delim ? Host : "<unknown host>", argv[2], argc > 4 ? argv[4] : ""); free(Dup); } } else { Channel = GetChannel(argv[2]); if (Channel != NULL) { Channel->RemoveUser(argv[3]); } } UpdateHostHelper(Reply); return bRet; } else if (argc > 2 && iRaw == 1) { if (Client != NULL) { if (strcmp(Client->GetNick(), argv[2]) != 0) { Client->WriteLine(":%s!%s NICK :%s", Client->GetNick(), m_Site ? m_Site : "*****@*****.**", argv[2]); } } free(m_CurrentNick); m_CurrentNick = strdup(argv[2]); free(m_Server); m_Server = strdup(Reply); } else if (argc > 2 && hashRaw == hashNick) { if (b_Me) { free(m_CurrentNick); m_CurrentNick = strdup(argv[2]); } Nick = NickFromHostmask(argv[0]); int i = 0; if (!b_Me && GetOwner()->GetClientConnectionMultiplexer() == NULL) { const char *AwayNick = GetOwner()->GetAwayNick(); if (AwayNick != NULL && strcasecmp(AwayNick, Nick) == 0) { WriteLine("NICK %s", AwayNick); } } while (hash_t<CChannel *> *ChannelHash = m_Channels->Iterate(i++)) { ChannelHash->Value->RenameUser(Nick, argv[2]); } free(Nick); } else if (argc > 1 && hashRaw == hashQuit) { bool bRet = ModuleEvent(argc, argv); Nick = NickFromHostmask(argv[0]); int i = 0; while (hash_t<CChannel *> *ChannelHash = m_Channels->Iterate(i++)) { ChannelHash->Value->RemoveUser(Nick); } free(Nick); return bRet; } else if (argc > 1 && (iRaw == 422 || iRaw == 376)) { int DelayJoin = GetOwner()->GetDelayJoin(); if (m_State != State_Connected) { const CVector<CModule *> *Modules = g_Bouncer->GetModules(); for (int i = 0; i < Modules->GetLength(); i++) { (*Modules)[i]->ServerLogon(GetOwner()->GetUsername()); } const char *ClientNick; if (Client != NULL) { ClientNick = Client->GetNick(); if (strcmp(m_CurrentNick, ClientNick) != 0) { Client->ChangeNick(m_CurrentNick); } } GetOwner()->Log("You were successfully connected to an IRC server."); g_Bouncer->Log("User %s connected to an IRC server.", GetOwner()->GetUsername()); } if (DelayJoin == 1) { m_DelayJoinTimer = g_Bouncer->CreateTimer(5, false, DelayJoinTimer, this); } else if (DelayJoin == 0) { JoinChannels(); } if (Client == NULL) { bool AppendTS = (GetOwner()->GetConfig()->ReadInteger("user.ts") != 0); const char *AwayReason = GetOwner()->GetAwayText(); if (AwayReason != NULL) { WriteLine(AppendTS ? "AWAY :%s (Away since the dawn of time)" : "AWAY :%s", AwayReason); } } const char *AutoModes = GetOwner()->GetAutoModes(); const char *DropModes = GetOwner()->GetDropModes(); if (AutoModes != NULL) { WriteLine("MODE %s +%s", GetCurrentNick(), AutoModes); } if (DropModes != NULL && Client == NULL) { WriteLine("MODE %s -%s", GetCurrentNick(), DropModes); } m_State = State_Connected; } else if (argc > 1 && strcasecmp(Reply, "ERROR") == 0) { if (strstr(Raw, "throttle") != NULL) { GetOwner()->ScheduleReconnect(120); } else { GetOwner()->ScheduleReconnect(5); } if (GetCurrentNick() != NULL && GetSite() != NULL) { g_Bouncer->LogUser(GetUser(), "Error received for user %s [%s!%s]: %s", GetOwner()->GetUsername(), GetCurrentNick(), GetSite(), argv[1]); } else { g_Bouncer->LogUser(GetUser(), "Error received for user %s: %s", GetOwner()->GetUsername(), argv[1]); } } else if (argc > 3 && iRaw == 465) { if (GetCurrentNick() != NULL && GetSite() != NULL) { g_Bouncer->LogUser(GetUser(), "G/K-line reason for user %s [%s!%s]: %s", GetOwner()->GetUsername(), GetCurrentNick(), GetSite(), argv[3]); } else { g_Bouncer->LogUser(GetUser(), "G/K-line reason for user %s: %s", GetOwner()->GetUsername(), argv[3]); } } else if (argc > 5 && iRaw == 351) { free(m_ServerVersion); m_ServerVersion = strdup(argv[3]); free(m_ServerFeat); m_ServerFeat = strdup(argv[5]); } else if (argc > 3 && iRaw == 5) { for (int i = 3; i < argc - 1; i++) { char *Dup = strdup(argv[i]); if (AllocFailed(Dup)) { return false; } char *Eq = strchr(Dup, '='); if (strcasecmp(Dup, "NAMESX") == 0) { WriteLine("PROTOCTL NAMESX"); } char *Value; if (Eq) { *Eq = '\0'; Value = strdup(++Eq); } else { Value = strdup(""); } m_ISupport->Add(Dup, Value); free(Dup); } } else if (argc > 4 && iRaw == 324) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->ClearModes(); Channel->ParseModeChange(argv[0], argv[4], argc - 5, &argv[5]); Channel->SetModesValid(true); } } else if (argc > 3 && hashRaw == hashMode) { Channel = GetChannel(argv[2]); if (Channel != NULL) { Channel->ParseModeChange(argv[0], argv[3], argc - 4, &argv[4]); } else if (strcmp(m_CurrentNick, argv[2]) == 0) { bool Flip = true, WasNull; const char *Modes = argv[3]; size_t Length = strlen(Modes) + 1; if (m_Usermodes != NULL) { Length += strlen(m_Usermodes); } WasNull = (m_Usermodes != NULL) ? false : true; m_Usermodes = (char *)realloc(m_Usermodes, Length); if (AllocFailed(m_Usermodes)) { return false; } if (WasNull) { m_Usermodes[0] = '\0'; } while (*Modes != '\0') { if (*Modes == '+') { Flip = true; } else if (*Modes == '-') { Flip = false; } else { if (Flip) { size_t Position = strlen(m_Usermodes); m_Usermodes[Position] = *Modes; m_Usermodes[Position + 1] = '\0'; } else { char *CurrentModes = m_Usermodes; size_t a = 0; while (*CurrentModes != '\0') { *CurrentModes = m_Usermodes[a]; if (*CurrentModes != *Modes) { CurrentModes++; } a++; } } } Modes++; } } UpdateHostHelper(Reply); } else if (argc > 4 && iRaw == 329) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->SetCreationTime(atoi(argv[4])); } } else if (argc > 4 && iRaw == 332) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->SetTopic(argv[4]); } } else if (argc > 5 && iRaw == 333) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->SetTopicNick(argv[4]); Channel->SetTopicStamp(atoi(argv[5])); } } else if (argc > 3 && iRaw == 331) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->SetNoTopic(); } } else if (argc > 3 && hashRaw == hashTopic) { Channel = GetChannel(argv[2]); if (Channel != NULL) { Channel->SetTopic(argv[3]); Channel->SetTopicStamp(g_CurrentTime); Channel->SetTopicNick(argv[0]); } UpdateHostHelper(Reply); } else if (argc > 5 && iRaw == 353) { Channel = GetChannel(argv[4]); if (Channel != NULL) { const char *nicks; const char **nickv; nicks = ArgTokenize(argv[5]); if (AllocFailed(nicks)) { return false; } nickv = ArgToArray(nicks); if (AllocFailed(nickv)) { ArgFree(nicks); return false; } int nickc = ArgCount(nicks); for (int i = 0; i < nickc; i++) { char *Nick = strdup(nickv[i]); char *BaseNick = Nick; if (AllocFailed(Nick)) { ArgFree(nicks); return false; } StrTrim(Nick, ' '); while (IsNickPrefix(*Nick)) { Nick++; } char *Modes = NULL; if (BaseNick != Nick) { Modes = (char *)malloc(Nick - BaseNick + 1); if (!AllocFailed(Modes)) { strmcpy(Modes, BaseNick, Nick - BaseNick + 1); } } Channel->AddUser(Nick, Modes); free(BaseNick); free(Modes); } ArgFreeArray(nickv); ArgFree(nicks); } } else if (argc > 3 && iRaw == 366) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->SetHasNames(); } } else if (argc > 9 && iRaw == 352) { const char *Ident = argv[4]; const char *Host = argv[5]; const char *Server = argv[6]; const char *Nick = argv[7]; const char *Realname = argv[9]; char *Mask; int rc = asprintf(&Mask, "%s!%s@%s", Nick, Ident, Host); if (!RcFailed(rc)) { UpdateHostHelper(Mask); UpdateWhoHelper(Nick, Realname, Server); free(Mask); } } else if (argc > 6 && iRaw == 367) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->GetBanlist()->SetBan(argv[4], argv[5], atoi(argv[6])); } } else if (argc > 3 && iRaw == 368) { Channel = GetChannel(argv[3]); if (Channel != NULL) { Channel->SetHasBans(); } } else if (argc > 3 && iRaw == 396) { free(m_Site); m_Site = strdup(argv[3]); if (AllocFailed(m_Site)) {} } else if (argc > 3 && hashRaw == hashPong && m_Server != NULL && strcasecmp(argv[2], m_Server) == 0 && m_EatPong) { m_EatPong = false; return false; } else if (argc > 3 && iRaw == 421) { m_FloodControl->Unplug(); return false; } if (GetOwner() != NULL) { return ModuleEvent(argc, argv); } else { return true; } }
void Execute() { if (CurrentVote.Voting) { Player->PrintToClient(PRINT_HIGH, "Vote already in progress."); return; } if (ArgCount() != 3) { Player->PrintToClient (PRINT_HIGH, "Use \"players\" to check the player IDs for kick-by-ID. Syntax:\n vote ban/kick n:id\n vote ban/kick p:playerName\n\n Example: vote ban/kick n:8\n Example: vote ban/kick p:Paril\n"); return; } String str = ArgGets(2); if (str.Count() < 3 || str[1] != ':' || (str[0] != 'p' && str[0] != 'n')) { Player->PrintToClient (PRINT_HIGH, "Syntax error. Type \"vote ban\" or \"vote kick\" to see syntax.\n"); return; } int playerToKick = -1; if (str[0] == 'p') { String playerName = str.Substring(2).ToLower(); if (playerName.IsNullOrEmpty()) { Player->PrintToClient (PRINT_HIGH, "Syntax error. Type \"vote ban\" or \"vote kick\" to see syntax.\n"); return; } for (int i = 1; i <= Game.MaxClients; ++i) { if (entity_cast<CPlayerEntity>(Game.Entities[i].Entity)->Client.Persistent.Name.Clone().ToLower() == playerName) { if (playerToKick != -1) { Player->PrintToClient (PRINT_HIGH, "Multiple players exist by that name. Type \"vote ban\" or \"vote kick\" to see how to ban by player number instead.\n"); return; } playerToKick = i; } } if (playerToKick == -1) { Player->PrintToClient (PRINT_HIGH, "Player does not exist.\n"); return; } } else { String playerNum = str.Substring(2); for (size_t i = 0; i < playerNum.Count(); ++i) { if (playerNum[i] < '0' || playerNum[i] > '9') { Player->PrintToClient (PRINT_HIGH, "Invalid player number.\n"); return; } } playerToKick = atoi(str.Substring(2).CString()); if (playerToKick <= 0 || playerToKick > Game.MaxClients) { Player->PrintToClient (PRINT_HIGH, "Invalid player number.\n"); return; } } CVoteKickBanData *voteData = QNew(TAG_GENERIC) CVoteKickBanData(ban, playerToKick); CurrentVote.StartVote(voteType, voteData, Player->Client.Persistent.Name); }
/** * CCore * * Creates a new shroudBNC application object. * * @param Config the main config object * @param argc argument counts * @param argv program arguments */ CCore::CCore(CConfig *Config, int argc, char **argv) { int i; m_Log = NULL; m_PidFile = NULL; WritePidFile(); m_Config = Config; m_SSLContext = NULL; m_SSLClientContext = NULL; m_Status = Status_Running; CacheInitialize(m_ConfigCache, Config, "system."); char *SourcePath = strdup(BuildPathLog("sbnc.log")); rename(SourcePath, BuildPathLog("sbnc.log.old")); free(SourcePath); m_PollFds.Preallocate(SFD_SETSIZE); m_Log = new CLog("sbnc.log", true); if (m_Log == NULL) { printf("Log system could not be initialized. Shutting down."); exit(EXIT_FAILURE); } m_Log->Clear(); Log("Log system initialized."); g_Bouncer = this; m_Config = Config; m_Args.SetList(argv, argc); m_Ident = new CIdentSupport(); m_Config = new CConfig("sbnc.conf", NULL); CacheInitialize(m_ConfigCache, m_Config, "system."); const char *Users; CUser *User; if ((Users = m_Config->ReadString("system.users")) == NULL) { if (!MakeConfig()) { Log("Configuration file could not be created."); Fatal(); } printf("Configuration has been successfully saved. Please restart shroudBNC now.\n"); exit(EXIT_SUCCESS); } const char *Args; int Count; Args = ArgTokenize(Users); if (AllocFailed(Args)) { Fatal(); } Count = ArgCount(Args); for (i = 0; i < Count; i++) { const char *Name = ArgGet(Args, i + 1); User = new CUser(Name); if (AllocFailed(User)) { Fatal(); } m_Users.Add(Name, User); } ArgFree(Args); m_Listener = NULL; m_ListenerV6 = NULL; m_SSLListener = NULL; m_SSLListenerV6 = NULL; time(&m_Startup); m_LoadingModules = false; m_LoadingListeners = false; InitializeSocket(); m_Capabilities = new CVector<const char *>(); m_Capabilities->Insert("multi-prefix"); m_Capabilities->Insert("znc.in/server-time-iso"); }
void GameEvent(CORE_DATA *cd) { switch (cd->event) { case EVENT_START: RegisterPlugin(OPENCORE_VERSION, "rabbit", "cycad", "1.0", __DATE__, __TIME__, "A rabbit bot", sizeof(USER_DATA), 0); /* set rabbit pid to nobody */ ud(cd)->rabbit_pid = PID_NONE; /* register rabbit command */ RegisterCommand(COMMAND_RABBIT, "!rabbit", "Rabbit", 2, CMD_PRIVATE, "<name>:<bounty>[:<special>]", "Start the rabbit game", NULL); break; case EVENT_LOGIN: /* set the bot's location to center */ SetPosition(16 * 512, 16 * 512, 0, 0); break; case EVENT_COMMAND: switch (cd->cmd_id) { case COMMAND_RABBIT: { int show_usage = 0; PLAYER_ID rpid = ud(cd)->rabbit_pid; if (rpid == PID_NONE) { /* rabbit game is not runnig */ if (cd->cmd_argc <= 1) { show_usage = 1; } else { char *cmd = cd->cmd_argr[1]; int nargs = ArgCount(cmd, ':'); if (nargs != 2 && nargs != 3) { show_usage = 1; } else { /* args to command are valid */ /* copy name out of command */ char rname[20]; DelimArgs(rname, sizeof(rname), cmd, 0, ':', 0); /* copy bounty out of command */ int bty = AtoiArg(cmd, 1, ':'); /* copy special out of command if it was specified */ int special = 0; if (nargs == 3) special = AtoiArg(cmd, 2, ':'); /* find the player specified on the command line */ PLAYER *rabbit = FindPlayerName(rname, MATCH_HERE | MATCH_PREFIX); if (rabbit) { /* player found, start the game */ start_rabbit_game(cd, rabbit, bty, special); } else { RmtMessageFmt(cd->cmd_name, "Player not found: %s", rname); } } } } else { /* rabbit game is already running */ PLAYER *p = FindPlayerPid(rpid, MATCH_HERE); RmtMessageFmt(cd->cmd_name, "Rabbit is already running (%s is the rabbit)", p ? p->name : "**UNKNOWN**"); } /* display usage if necessary */ if (show_usage) RmtMessageFmt(cd->cmd_name, "Usage: %s <name>:<bounty>[:<special>]", cd->cmd_argv[0]); } default: break; } break; case EVENT_UPDATE: if (ud(cd)->rabbit_pid == cd->p1->pid) { /* if the update is for the rabbit */ if (cd->p1->status & STATUS_SAFE) { /* check if the rabbit is in safe */ /* the rabbit entered safe, end the game */ ArenaMessageFmt("%s has lost the rabbit game by entering safe!", cd->p1->name); ud(cd)->rabbit_pid = PID_NONE; } } break; case EVENT_TIMER: if (ud(cd)->rabbit_pid != PID_NONE) { /* if the rabbit game is running */ /* find the rabbit */ PLAYER *p = FindPlayerPid(ud(cd)->rabbit_pid, MATCH_HERE); if (p) { if (ud(cd)->where_timer == cd->timer_id) { /* a *where timer expired, send the next one and look for response */ PrivMessage(p, "*where"); ud(cd)->expecting_where = 1; } else if (ud(cd)->gameover_timer == cd->timer_id) { /* the game over timer expired, the rabbit didnt die and he won */ ArenaMessageFmt("%s wins the rabbit game by staying alive!", p->name); ud(cd)->rabbit_pid = PID_NONE; } } else { /* rabbit not found, this should never happen! */ } } case EVENT_MESSAGE: /* * Only look for a response of the game is running, the bot is expecting *where, * and the message type is an arena message. */ if (ud(cd)->rabbit_pid != PID_NONE && ud(cd)->expecting_where && cd->msg_type == MSG_ARENA) { /* message is a possible *where response */ /* find the rabbit */ PLAYER *p = FindPlayerPid(ud(cd)->rabbit_pid, MATCH_HERE); if (p) { char where_prefix[32]; snprintf(where_prefix, 32, "%s: ", p->name); where_prefix[32 - 1] = '\0'; /* * Verify that this is *where output by looking for "rabbit: " at the * beginning of the string. */ if (strncasecmp(where_prefix, cd->msg, strlen(where_prefix)) == 0) { /* this must be a *where response, process it */ char loc[4]; snprintf(loc, 4, "%s", &cd->msg[strlen(where_prefix)]); loc[4 - 1] = '\0'; /* announce the rabbits location */ ArenaMessageFmt(">>> Rabbit %s is at %-3s <<<", p->name, loc); /* set the next *where timer */ ud(cd)->where_timer = SetTimer(30 * 1000, 0, 0); /* * The bot wont be looking for *where responses until the * next time it sends the command, so turn parsing off * for now. */ ud(cd)->expecting_where = 0; } } } break; case EVENT_KILL: if (cd->p1->pid == ud(cd)->rabbit_pid) { /* the rabbit died */ ArenaMessageFmt("%s wins the rabbit game by killing Rabbit %s!", cd->p2->name, cd->p1->name); ud(cd)->rabbit_pid = PID_NONE; } break; case EVENT_LEAVE: if (ud(cd)->rabbit_pid == cd->p1->pid) { /* the rabbit left */ ArenaMessageFmt("%s has lost the rabbit game by leaving the arena!", cd->p1->name); ud(cd)->rabbit_pid = PID_NONE; } break; case EVENT_CHANGE: if (ud(cd)->rabbit_pid == cd->p1->pid) { /* the rabbit changed ship */ ArenaMessageFmt("%s has lost the rabbit game by changing ship/freq!", cd->p1->name); ud(cd)->rabbit_pid = PID_NONE; } break; } }