Logo Search packages:      
Sourcecode: yics version File versions  Download package

ropcodes.c

/*
 * YICS: Connect a FICS interface to the Yahoo! Chess server.
 * Copyright (C) 2004  Chris Howie
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sockets.h"
#include "debug.h"
#include "console.h"
#include "ropcodes.h"
#include "topcodes.h"
#include "globals.h"
#include "network.h"
#include "types.h"
#include "util.h"
#include "version.h"
#include "vars.h"
#include "formula.h"
#include "lists.h"

void rop_option(String *);          /* 0x14 */
void rop_tableoptions(String *);    /* 0x30 */
void rop_buddylist(String *);       /* 0x31 */
void rop_tell(String *);            /* 0x33 */
void rop_ignorelist(String *);            /* 0x34 */
void rop_topcode(String *);         /* 0x3d */
void rop_alert(String *);           /* 0x61 */
void rop_shout(String *);           /* 0x63 */
void rop_deltable(String *);        /* 0x64 */
void rop_entry(String *);           /* 0x65 */
void rop_ping(String *);            /* 0x67 */
void rop_pingend(String *);         /* 0x68 */
void rop_invitation(String *);            /* 0x69 */
void rop_tableentry(String *);            /* 0x6a */
void rop_pingbegin(String *);       /* 0x6b */
void rop_tabledeparture(String *);  /* 0x6c */
void rop_introdone(String *);       /* 0x6d */
void rop_newtable(String *);        /* 0x6e */
void rop_tableprotection(String *); /* 0x70 */
void rop_booted(String *);          /* 0x71 */
void rop_seatupdate(String *);            /* 0x73 */
void rop_ratingupdate(String *);    /* 0x74 */
void rop_decline(String *);         /* 0x76 */
void rop_departure(String *);       /* 0x78 */
void rop_finger(String *packet);    /* 0x79 */

RoomOpcode ropcodes[] = {
      {0x14,      rop_option},
      {0x30,      rop_tableoptions},
      {0x31,      rop_buddylist},
      {0x33,      rop_tell},
      {0x34,      rop_ignorelist},
      {0x3d,      rop_topcode},
      {0x61,      rop_alert},
      {0x63,      rop_shout},
      {0x64,      rop_deltable},
      {0x65,      rop_entry},
      {0x66,      NULL},      /* unknown */
      {0x67,      rop_ping},
      {0x68,      rop_pingend},
      {0x69,      rop_invitation},
      {0x6a,      rop_tableentry},
      {0x6b,      rop_pingbegin},
      {0x6c,      rop_tabledeparture},
      {0x6d,      rop_introdone},
      {0x6e,      rop_newtable},
      {0x6f,      NULL},      /* unknown */
      {0x70,      rop_tableprotection},
      {0x71,      rop_booted},
      {0x73,      rop_seatupdate},
      {0x74,      rop_ratingupdate},
      {0x76,      rop_decline},
      {0x77,      NULL},      /* unknown */
      {0x78,      rop_departure},
      {0x79,      rop_finger},
      {-1,  NULL},
};

#if STEALTH
# define IsIdent(x,y) 0
#else
static bool IsIdent(String *who, String *what) {
      String *packet, *ident;

      if (!strcmp(what->string, "/ytoics") ||
          !strcmp(what->string, "/yics"  )) {
            packet = packutfString(StringNull(), who);

            ident = getIdent(StringNull());
            packutfStringP(packet, ident);
            nprintropString(ROP_TELL, packet);

            StringFree(packet);
            StringFree(ident);

#if !SEE_IDENT
            return true;
#endif
      }

      return false;
}
#endif

static void checkSeek(Table *table) {
      char srating[16];
      bool white;
      int i;
      Player *p;

      if (!variables[VAR_SEEK].number)
            return;

      if (table->protection == 2)
            return;

      for (i = 0; i < PLAYER_MAX; i++)
            if (table->observers[i] == pme)
                  return;

      if (table->players[0] != NULL) {
            if (table->players[1] != NULL)
                  return;

            p = table->players[0];
            white = true;
      } else if (table->players[1] != NULL) {
            p = table->players[1];
            white = false;
      } else {
            return;
      }

      if (inList(&lists[LIST_NOPLAY], p->lhandle))
            return;

      table->players[white ? 1 : 0] = pme;
      i = checkFormula(table);
      table->players[white ? 1 : 0] = NULL;
      if (!i)
            return;

      prating(srating, p->rating, 4);

      iprintf("\n%s (%s) seeking %d %d %srated %s [%s] m (\"play %d\" to respond)\n",
            p->handle, srating, tabletime(table), tableinc(table),
            tablerated(table) ? "" : "un", strGameType(table),
            white ? "white" : "black", table->number);
      prompt();
}

void rop_option(String *packet) {   /* 0x14 */
      String *key, *value;

      key = unpackutfStringP(StringNull(), packet);
      value = unpackutfStringP(StringNull(), packet);

      iprintf("\nClient option %s set to %s.\n", key->string, value->string);
      prompt();

      if (clientOptions == NULL)
            clientOptions = createOption(key->string, value->string);
      else
            setOption(clientOptions, key->string, value->string);

      StringFree(key);
      StringFree(value);
}

void rop_tableoptions(String *packet) {   /* 0x30 */
      uchar number;
      unsigned short optcount = 0;
      Table *table;
      String *key, *value;
      Option *options = NULL;

      number = (uchar)packet->string[0];
      table = tables[number];
      if (table == NULL)
            return;

      memcpy(&optcount, &packet->string[1], 2);
      optcount = ntohs(optcount);

      StringSet(packet, &packet->string[3], packet->length - 3);

      while (optcount--) {
            key = unpackutfStringP(StringNull(), packet);
            value = unpackutfStringP(StringNull(), packet);

            if (options == NULL)
                  options = createOption(key->string, value->string);
            else
                  setOption(options, key->string, value->string);

            StringFree(key);
            StringFree(value);
      }

      destroyOptions(table->options);
      table->options = options;

      checkSeek(table);

      /* Check formula */
      if (((table->players[0] == pme) || (table->players[1] == pme)) &&
                  (table->host != pme)) {
            if (!checkFormula(table)) {
                  nprinttop(table->number, TOP_STAND, NULL, 0);

                  value = StringNew("Sorry, the table's options do not "
                              "fit my formula.", -1);
                  value = packutfString(value, value);
                  nprinttopString(table->number, TOP_KIBITZ, value);
                  StringFree(value);

                  sysiprint("The host has modified the settings, which "
                              "no longer match your formula.  "
                              "Standing up.\n");
            }
      }
}

void rop_buddylist(String *packet) {      /* 0x31 */
      buildList(&lists[LIST_NOTIFY], packet);
}

void rop_tell(String *packet) {     /* 0x33 */
      String *who, *what;

      who = unpackutfStringP(StringNull(), packet);

      if (inList(&lists[LIST_CENSOR], who->string)) {
            StringFree(who);
            return;
      }

      what = unpackutfStringP(StringNull(), packet);

      if (!IsIdent(who, what)) {
            realHandle(who);
            iprintf("\n%s tells you: %s\n", who->string, what->string);
            prompt();
      }

      StringFree(who);
      StringFree(what);
}

void rop_ignorelist(String *packet) {     /* 0x34 */
      buildList(&lists[LIST_CENSOR], packet);
}

void rop_topcode(String *packet) {  /* 0x3d */
      uchar number, opcode;
      TableOpcode *search = topcodes;
      Table *table;
#ifdef MEMDEBUGP
#  if MEMDEBUGP
      int lstr;
#  endif
#endif

      number = (uchar)packet->string[0];
      opcode = (uchar)packet->string[1];

      if (tables[number] == NULL)
            return;
      table = tables[number];

      StringSet(packet, &packet->string[2], packet->length - 2);

      while (search->opcode != -1) {
            if (search->opcode == opcode) {

            #ifdef MEMDEBUGP
            #  if MEMDEBUGP
                  lstr = string_count;
            #  endif
            #endif

                  if (search->handler != NULL)
                        search->handler(table, packet);

            #ifdef MEMDEBUGP
            #  if MEMDEBUGP
                  if (string_count > lstr)
                        printf("Possible leak, topcode %02x: %d -> %d\n",
                              opcode, lstr, string_count);
            #  endif
            #endif

                  return;
            }
            search++;
      }
}

void rop_alert(String *packet) {    /* 0x61 */
      unpackutfString(packet, packet);

      iprint("Alert:\n");
      iprint(packet->string);
      iprint("\n");
      prompt();
}

void rop_shout(String *packet) {    /* 0x63 */
      String *who, *what;
      Player *p;

      who = unpackutfStringP(StringNull(), packet);

      if (inList(&lists[LIST_CENSOR], who->string)) {
            StringFree(who);
            return;
      }

      what = unpackutfStringP(StringNull(), packet);

      p = findPlayer(who->string);

      if (!IsIdent(who, what) && variables[VAR_SHOUT].number) {
            if (p != NULL)
                  StringSet(who, p->handle, -1);
            if (p != pme)
                  iprint("\n");

            iprintf("%s shouts: %s\n", who->string, what->string);
            prompt();
      }

      StringFree(who);
      StringFree(what);
}

void rop_deltable(String *packet) { /* 0x64 */
      uchar number;
      Table *table;

      number = (uchar)packet->string[0];
      if (delInvite(NULL, number)) {
            iprintf("Table %d was destroyed; removing invitations.\n", number);
            prompt();
      }

      table = tables[number];
      if (table == NULL)
            return;

      destroyOptions(table->options);
      free(table);
      tables[number] = NULL;
}

void rop_entry(String *packet) {    /* 0x65 */
      String *lc, *rc;
      Player *p = malloc(sizeof(Player));
      int index = 0;

      while ((index < PLAYER_MAX) && (players[index] != NULL))
            index++;

      if (index == PLAYER_MAX) {
            if (p != NULL)
                  free(p);
            return;
      }

      lc = unpackutfStringP(StringNull(), packet);
      rc = unpackutfStringP(StringNull(), packet);

      if ((lc == NULL) || (rc == NULL) || (p == NULL)) {
            if (lc != NULL)
                  StringFree(lc);
            if (rc != NULL)
                  StringFree(rc);
            if (p != NULL)
                  free(p);
            return;
      }

      p->lhandle = malloc(lc->length + 1);
      p->handle = malloc(rc->length + 1);

      if ((p->lhandle == NULL) || (p->handle == NULL)) {
            if (p->lhandle != NULL)
                  free(p->lhandle);
            if (p->handle != NULL)
                  free(p->handle);
            StringFree(lc);
            StringFree(rc);
            free(p);
            return;
      }

      mstrncpy(p->lhandle, lc->string, lc->length + 1);
      mstrncpy(p->handle, rc->string, rc->length + 1);
      p->rating = PROVISIONAL;
      p->ping = -1;

      StringFree(lc);
      StringFree(rc);
      players[index] = p;

      if (!istrcmp(p->handle, handle))
            pme = p;

      if (prompting) {
            if (variables[VAR_PIN].number) {
                  iprintf("[%s has connected.]\n", p->handle);
                  prompt();
            }

            if (inList(&lists[LIST_NOTIFY], p->lhandle)) {
                  iprintf("Notification: %s has arrived.\n", p->handle);
                  prompt();
            }
      }
}

void rop_ping(String *packet) {           /* 0x67 */
      String *who;

      who = unpackutfString(StringNull(), packet);
      if (inList(&lists[LIST_CENSOR], who->string)) {
            StringFree(who);
            return;
      }

      nprintropString(ROP_PONG, packet);

      iprintf("You were pinged by %s.\n", realHandle(who)->string);
      prompt();

      StringFree(who);
}

void rop_pingend(String *packet) {  /* 0x68 */
      Player *p;
      int ptime;

      unpackutfString(packet, packet);
      if ((p = findPlayer(packet->string)) == NULL)
            return;

      if (p->ping < 0)
            return;

      ptime = (int)(gettimeofdayll() - p->ping);
      iprintf("ROBOadmin(*)(TD) tells you: Ping-info for %s: 3 packets "
            "transmitted, 3 packets received, 0%% packet loss\n",
            p->handle);
      prompt();
      iprintf("ROBOadmin(*)(TD) tells you: Ping-info for %s: "
            "round-trip min/avg/max = %d.0/%d.0/%d.0 ms\n",
            p->handle, ptime, ptime, ptime);
      prompt();

      p->ping = -1;
}

void rop_invitation(String *packet) {     /* 0x69 */
      uchar number;
      String *who;
      String *reject;
      Player *p;
      Table *table;
      int j;

      number = (uchar)packet->string[0];
      if (tables[number] == NULL)
            return;

      table = tables[number];

      StringSet(packet, &packet->string[1], packet->length - 1);
      who = unpackutfString(StringNull(), packet);

      if (inList(&lists[LIST_CENSOR], who->string)) {
            reject = StringNew("You are on my ignore list", -1);

            packutfString(who, who);
            packutfStringP(who, reject);

            nprintropString(ROP_DECLINE, who);

            StringFree(reject);
            StringFree(who);

            return;
      }

      p = findPlayer(who->string);

      StringSet(who, p->handle, -1);
      iprintf("%s has invited you to take a seat at table #%d.\n",
            who->string, number);
      StringFree(who);

      prompt();

      for (j = 0; j < PLAYER_MAX; j++)
            if (table->observers[j] == pme)
                  return;

      addInvite(p, number, INV_INVITE);
}

void rop_tableentry(String *packet) {     /* 0x6a */
      String *who;
      uchar number;
      Player *p;
      Table *table;
      int i;

      who = unpackutfStringP(StringNull(), packet);
      number = (uchar)packet->string[0];

      p = findPlayer(who->string);

      if (p == NULL) {
            StringFree(who);
            return;
      }

      table = tables[number];
      if (table == NULL) {
            StringFree(who);
            return;
      }

      for (i = 0; i < PLAYER_MAX; i++) {
            if (table->observers[i] == NULL) {
                  table->observers[i] = p;
                  break;
            }
      }

      if (p == pme) {
            iprintf("You are now observing game %d.\n", number);
            prompt();
            if (primary == -1)
                  primary = number;
      } else {
            for (i = 0; i < PLAYER_MAX; i++) {
                  if (table->observers[i] == pme) {
                        iprintf("Game %d: %s is now observing.\n",
                              number, p->handle);
                        prompt();
                        break;
                  }
            }
      }

      StringFree(who);
}

void rop_pingbegin(String *packet) {      /* 0x6b */
      Player *p;

      unpackutfString(packet, packet);
      if ((p = findPlayer(packet->string)) == NULL)
            return;

      p->ping = gettimeofdayll();
}

void rop_tabledeparture(String *packet) { /* 0x6c */
      String *who;
      uchar number;
      Player *p;
      Table *table;
      int i, j;

      who = unpackutfStringP(StringNull(), packet);
      number = (uchar)packet->string[0];

      p = findPlayer(who->string);

      if (p == NULL) {
            StringFree(who);
            return;
      }

      table = tables[number];
      if (table == NULL) {
            StringFree(who);
            return;
      }

      for (i = 0; i < PLAYER_MAX; i++) {
            if (table->observers[i] == p) {
                  table->observers[i] = NULL;
                  break;
            }
      }

      if (p == pme) {
            if (!table->finished) {
                  iprintf("\n{Game %d (? vs. ?) unknown}\n",
                        table->number);
            }

            /* So seeking doesn't screw up if we're the host. */
            table->host = NULL;

            iprintf("Removing game %d from observation list.\n", number);
            prompt();
            if (primary == number) {
                  primary = -1;
                  for (i = 0; i < TABLE_MAX; i++) {
                        if (tables[i] == NULL)
                              continue;

                        table = tables[i];
                        for (j = 0; j < PLAYER_MAX; j++) {
                              if (table->observers[j] == pme) {
                                    primary = i;
                                    break;
                              }
                        }

                        if (primary != -1)
                              break;
                  }
            }
      } else {
            for (i = 0; i < PLAYER_MAX; i++) {
                  if (table->observers[i] == pme) {
                        iprintf("Game %d: %s is no longer observing.\n",
                              number, p->handle);
                        prompt();
                        break;
                  }
            }
      }

      StringFree(who);
}

void rop_introdone(String *packet) {      /* 0x6d */
      String *mess;

      mess = unpackutfString(StringNull(), packet);
      if ((mess != NULL) && (mess->length != 0)) {
            iprint("*** Server information: ");
            iprint(mess->string);
            prompt();
      }
      StringFree(mess);

      login_complete = true;
}

void rop_newtable(String *packet) { /* 0x6e */
      uchar number;
      unsigned short optcount = 0;
      int unknown = 0;
      Option *options = NULL;
      String *key, *value;
      Table *table;
      Game *game;

      number = (uchar)packet->string[0];
      memcpy(&optcount, &packet->string[1], 2);
      optcount = ntohs(optcount);

      StringSet(packet, &packet->string[3], packet->length - 3);

      while (optcount--) {
            key = unpackutfStringP(StringNull(), packet);
            value = unpackutfStringP(StringNull(), packet);

            if (options == NULL)
                  options = createOption(key->string, value->string);
            else
                  setOption(options, key->string, value->string);

            StringFree(key);
            StringFree(value);
      }

      if (packet->string[0]) {
            memcpy(&unknown, packet->string, 4);
            unknown = ntohl(unknown);
            iprintf("\nWARNING: Opcode 6e has extra parameter: %d\n",
                  unknown);
            prompt();
      }

      table = malloc(sizeof(Table));
      game = malloc(sizeof(Game));
      if ((table == NULL) || (game == NULL)) {
            if (table != NULL)
                  free(table);
            if (game != NULL)
                  free(game);
            return;
      }

      memset(table, 0, sizeof(Table));
      memset(game, 0, sizeof(Game));
      initGame(game);

      table->number = number;
      table->options = options;
      table->protection = 0;
      table->players[0] = NULL;
      table->players[1] = NULL;
      table->host = NULL;
      memset(table->observers, 0, sizeof(table->observers));
      table->game = game;
      table->start[0] = false;
      table->start[1] = false;
      table->finished = false;
      table->inprogress = false;
      table->result = "*";

      if (tables[number] != NULL) {
            destroyOptions(tables[number]->options);
            free(tables[number]);
      }

      tables[number] = table;
}

void rop_tableprotection(String *packet) {      /* 0x70 */
      uchar number, protection;
      Table *table;

      number = (uchar)packet->string[0];
      protection = (uchar)packet->string[1];

      table = tables[number];
      if (table == NULL)
            return;

      table->protection = protection;
}

void rop_booted(String *packet) {   /* 0x71 */
      uchar number;
      String *who;

      number = (uchar)packet->string[0];
      StringSet(packet, &packet->string[1], packet->length - 1);
      who = unpackutfString(StringNull(), packet);

      iprintf("%s has booted you from table %d.\n", who->string,
            number);
      prompt();

      StringFree(who);

      /* Not unobserving means that the server will disconnect from the
       * client after a few seconds.  Too bad...
       */
      nprintrop(ROP_UNOBSERVE, (char *)&number, 1);
}

void rop_seatupdate(String *packet) {     /* 0x73 */
      uchar number, color;
      String *who;
      String *msg;
      Table *table;
      Player *old;
      Player *new;
      int i;

      char *errmsg_toplayer = NULL;
      char *errmsg_touser = NULL;

      number = (uchar)packet->string[0];
      color  = (uchar)packet->string[1];

      StringSet(packet, &packet->string[2], packet->length - 2);
      who = unpackutfStringP(StringNull(), packet);

      table = tables[number];
      if (table == NULL) {
            StringFree(who);
            return;
      }

      old = table->players[color];

      new = (who->length == 0) ? NULL : findPlayer(who->string);
      table->players[color] = new;

      for (i = 0; i < PLAYER_MAX; i++) {
            if (table->observers[i] == pme) {
                  if (who->length != 0) {
                        iprintf("Game %d: %s sits down as %s.\n",
                              number, phandle(new),
                              (color == 0) ? "white" : "black");
                  } else {
                        iprintf("Game %d: %s stands up.\n",
                              number, phandle(old));
                  }

                  prompt();
                  break;
            }
      }

      checkSeek(table);

      if ((new != NULL) &&
                  ((table->players[0] == pme) || (table->players[1] == pme)) &&
                  (new != pme)) {
            if (inList(&lists[LIST_NOPLAY], new->lhandle)) {
                  errmsg_toplayer = "Sorry, you are on my ignore list.";
                  errmsg_touser = "is on your ignore list";
            } else if (!checkFormula(table)) {
                  errmsg_toplayer = "Sorry, you do not fit my formula.";
                  errmsg_touser = "does not fit your formula";
            }

            if (errmsg_toplayer != NULL) {
                  if (table->host == pme) {
                        StringSet(who, new->lhandle, -1);
                        packutfString(who, who);
                        nprinttopString(table->number, TOP_BOOT, who);

                        msg = StringNew(errmsg_toplayer, -1);
                        packutfStringP(who, msg);
                        StringFree(msg);

                        nprintropString(ROP_TELL, who);
                  } else {
                        nprinttop(table->number, TOP_STAND, NULL, 0);

                        StringSet(who, errmsg_toplayer, -1);
                        packutfString(who, who);
                        nprinttopString(table->number, TOP_KIBITZ, who);
                  }

                  sysiprintf("%s %s.  %s and notifying %s\n",
                              new->handle, errmsg_touser,
                              (table->host == pme) ? "Booting" : "Standing up,",
                              new->handle);
            }
      }

      StringFree(who);
}

void rop_ratingupdate(String *packet) {   /* 0x74 */
      String *lh = unpackutfStringP(StringNull(), packet);
      Player *p = findPlayer(lh->string);

      StringFree(lh);
      if (p == NULL)
            return;

      memcpy(&p->rating, packet->string, 2);
      p->rating = ntohs(p->rating);
}

void rop_decline(String *packet) {  /* 0x76 */
      String *lh = unpackutfStringP(StringNull(), packet);
      String *reason = unpackutfStringP(StringNull(), packet);
      Player *p = findPlayer(lh->string);

      iprintf("%s has declined your invitation.\nReason: %s\n", phandle(p),
                  reason->string);
      prompt();

      StringFree(lh);
      StringFree(reason);
}

void rop_departure(String *packet) {      /* 0x78 */
      String *lh = unpackutfStringP(StringNull(), packet);
      String *handle = NULL;
      int i = 0;
      bool wasme = false;

      if (!strcmp(lh->string, pme->lhandle)) {
            nputc('X');
            wasme = true;
      }

      while (i < PLAYER_MAX) {
            if ((players[i] != NULL) &&
                        !strcmp(players[i]->lhandle, lh->string)) {
                  if (delInvite(players[i], 0)) {
                        iprintf("%s departed; removing invitations.\n", players[i]->handle);
                        prompt();
                  }
                  if (players[i]->ping != -1) {
                        iprintf("%s departed; ping cancelled.\n", players[i]->handle);
                        prompt();
                  }
                  if (players[i] == lasttell)
                        lasttell = NULL;
                  if (players[i] == lastopp)
                        lastopp = NULL;
                  handle = StringNew(players[i]->handle, -1);
                  free(players[i]->handle);
                  free(players[i]->lhandle);
                  free(players[i]);
                  players[i] = NULL;
                  if (wasme)
                        pme = NULL;
                  break;
            }
            i++;
      }

      if (prompting && (handle != NULL) && !wasme) {
            if (variables[VAR_PIN].number) {
                  iprintf("[%s has disconnected.]\n", handle->string);
                  prompt();
            }

            if (inList(&lists[LIST_NOTIFY], handle->string)) {
                  iprintf("Notification: %s has departed.\n", handle->string);
                  prompt();
            }
      }

      if (handle != NULL)
            StringFree(handle);
}

void rop_finger(String *packet) {   /* 0x79 */
      String *p, *info;
      Player *pl = NULL;
      int idle = 0, total = 0, rating = 0, wins = 0,
            losses = 0, draws = 0, streak = 0, abandoned = 0;
      float rd = 50.0;
      Option *pi = NULL;
      static char key[1024], value[1024];
      char *kvp = key, *infop;
      char state = 0;
      static Table *obs[TABLE_MAX];
      Table **op;

      p = unpackutfStringP(StringNull(), packet);
      info = unpackutfStringP(StringNull(), packet);

      if ((pl = findPlayer(p->string)) == NULL) {
            iprintf("Error getting %s's information: pl is null.\n",
                  p->string);
            prompt();
            StringFree(p);
            StringFree(info);
            return;
      }

      memcpy(&idle, packet->string, 4);
      idle = ntohl(idle) / 1000;

      for (infop = info->string; ; infop++) {
            if ((*infop == '\n') || (*infop == '\0')) {
                  *kvp = '\0';
                  kvp = key;
                  if (state == 2) {
                        lowercase(key);
                        if (pi == NULL)
                              pi = createOption(key, value);
                        else
                              setOption(pi, key, value);
                  }

                  if (*infop == '\0')
                        break;

                  state = 0;
            } else if (state == 0) {
                  if (*infop == ':') {
                        state = 1;
                        *kvp = '\0';
                        kvp = value;
                  } else {
                        *(kvp++) = *infop;
                  }
            } else if ((state == 1) && (*infop != ' ')) {
                  state = 2;
                  *(kvp++) = *infop;
            } else {
                  *(kvp++) = *infop;
            }
      }

      StringSet(p, pl->handle, -1);
      iprintf("Information on %-16s    ", p->string);

      if (idle > 59) {
            kvp = "mins";
            idle /= 60;
      } else {
            kvp = "secs";
      }
      iprintf("On for: ? mins   Idle: %d %s\n", idle, kvp);

      observing(obs, pl);
      if (obs[0] != NULL) {
            iprintf("(%s is observing game(s) ", p->string);

            if (obs[1] == NULL) {
                  iprintf("%d)\n", obs[0]->number);
            } else {
                  for (op = obs, total = 0; *op != NULL; op++, total++);

                  op = obs;
                  while (total--) {
                        iprintf("%d", (*(op++))->number);

                        if (total > 1)
                              iprint(", ");
                        else if (total == 1)
                              iprint(" and ");
                  }

                  iprint(")\n");
            }
      }

      iprint("\n");

      total = findOptionLong(pi, "games completed");

      if (total < 20)
            rd = 350 - ((float)total / 20 * 270);

      rating = findOptionLong(pi, "rating");
      wins = findOptionLong(pi, "wins");
      losses = findOptionLong(pi, "losses");
      draws = findOptionLong(pi, "draws");

      snprintf(key, sizeof(key), " %4d    %5.1f %6d %6d %6d %6d\n",
            rating, rd, wins, losses, draws, total);

      iprint("         rating     RD     win   loss   draw  total   best\n");
      iprint("Blitz    ");
      iprint(key);
      iprint("Lightning");
      iprint(key);
      iprint("Standard ");
      iprint(key);
      iprint("\n");

      streak = findOptionLong(pi, "streak");

      kvp = (streak < 0) ? "losses" : "wins";
      if (streak < 0)
            streak *= -1;

      abandoned = findOptionLong(pi, "abandoned games");

      snprintf(key, sizeof(key), " 1: Streak: %d %s\n"
                 " 2: Abandoned games: %d\n",
            streak, kvp, abandoned);
      iprint(key);

      prompt();
      destroyOptions(pi);
      StringFree(p);
      StringFree(info);
}

Generated by  Doxygen 1.6.0   Back to index