main.vala 4.25 KB
Newer Older
1 2 3 4 5 6 7
/*
 * A sample bot.
 * Currently it is dummy code only to develop the API. It doesn't compile and
 * it probably don't use the better API ever. Let's see.
 */


8
public class Bot
9
{
10
  private MainLoop          loop   = null;
11
  private OVCCClient.Client client = null;
12 13
  
  public bool join (OVCCClient.Server server)
14
    throws Error
15
  {
16
    uint            player_suffix = 7;
17

18 19
    client = new OVCCClient.Client ();

20
    /* connect to the server */
21
    client.bind_to (server);
22 23 24

    /* login to the server, choosing an available nickname */
    debug ("Trying to login...");
25
    do {
26
      try {
27
        client.login ("""Clever bot %03u""".printf (player_suffix));
28
        break;
29
      } catch (OVCCClient.ServerError.NICKNAME_IN_USE e) {
30
        player_suffix++;
31
      } catch (OVCCClient.ServerError.MISSING_AUTHENTICATION e) {
32
        leave ();
33
        throw e; /* avoid infinite loop */
34
      } catch (Error e) {
35
        leave ();
36
        throw e;
37 38
      }
    }
39
    while (true);
40 41
    debug ("Logged in with player_suffix = %u", player_suffix);

42
    /* join any open table */
43
    debug ("Trying to join a table...");
44
    try {
45
      client.join_table (-1);
46
    } catch (Error e) {
47
      leave ();
48
      throw e;
49 50
    }
    debug ("Joined");
51 52

    /* start listening to the server */
53
    client.start_listening ();
54
    
55
    /* react on game state changes */
56
    client.game.notify["state"].connect ((s, p) => {
57 58 59 60 61 62 63 64 65 66 67
      switch (((OVCC.Game)s).state)
      {
        case OVCC.GameState.FINISHED:
          loop.quit ();
          debug ("We're done, bye!");
          break;
        case OVCC.GameState.ABORTED:
          loop.quit ();
          debug ("Abnormal game termination!");
          break;
      }
68 69
    });
    /* we should place a tile? OK, why not */
70
    client.place_tile.connect ((tile) => {
71
      debug ("Seems we should place a tile...");
72
      client.game.board.foreach ((b, p, t) => {
73 74 75 76 77 78 79 80 81 82 83
        for (var i = 0; i < 4; i++) {
          var npos = p;
          
          switch (i) {
            case 0: npos.y--; break; /* top */
            case 1: npos.x++; break; /* right */
            case 2: npos.y++; break; /* bottom */
            case 3: npos.x--; break; /* left */
          }
          for (var j = 0; j < 4; j++) {
            /* FIXME: this should probably be asynchronous... */
84
            if (client.player.place_tile (npos)) {
85 86 87 88 89 90 91 92 93 94
              return false;
            } else {
              tile.rotate (1);
            }
          }
        }
        return true;
      });
    });
    /* we should place a pawn? let's do so */
95
    client.place_pawn.connect ((game, tile) => {
96 97 98 99 100
      debug ("We're asked to place a pawn!");
      foreach (var o in tile.objects) {
        /* we guess all pawns can go anywhere another can -- which isn't true
         * using some extensions, but it doesn't matter that much. */
        /* FIXME: this should probably also be asynchronous... */
101 102 103
//         if (game.place_pawn (player.pawns.nth_data (0), o)) {
//           break;
//         }
104 105
      }
    });
106 107

    return true;
108
  }
109 110 111 112 113 114 115

  public void leave ()
  {
    client.leave ();
    client = null;
    loop.quit ();
  }
116 117 118 119 120
  
  public Bot (MainLoop l)
  {
    loop = l;
  }
121 122
}

123 124 125 126 127 128

#if HAVE_POSIX
private static void signal_handler (int sig)
{
  debug ("Caught signal %d, exiting", sig);
  try {
129
    bot.leave ();
130
  } catch (Error e) {
131
    warning ("Error leaving from server: %s", e.message);
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
  }
  Posix.exit (2);
}

private static void setup_signal_handlers ()
{
  Posix.sigaction_t s = {};
  s.sa_handler = signal_handler;
  Posix.sigemptyset (s.sa_mask);
  s.sa_flags = 0;
  
  Posix.sigaction (Posix.SIGQUIT, s, null);
  Posix.sigaction (Posix.SIGTERM, s, null);
  Posix.sigaction (Posix.SIGINT, s, null);
}
#endif


Bot               bot     = null;

152
public int main (string[] args)
153
{
154 155
  MainLoop          loop    = null;
  OVCCClient.Server server  = null;
156 157 158 159 160 161 162 163 164 165
  var     host = "localhost";
  uint16  port = 0xdead;
  
  if (args.length > 1) {
    host = args[1];
  }
  if (args.length > 2) {
    port = (uint16)int.parse (args[2]);
  }
  
166 167
  loop = new MainLoop ();
  bot = new Bot (loop);
168
  server = new OVCCClient.Server (host, port);
169 170 171 172
  
#if HAVE_POSIX
  setup_signal_handlers ();
#endif
173
  
174
  try {
175 176
    bot.join (server);
    loop.run ();
177 178 179
  } catch (Error e) {
    warning ("Failed to join on the server: %s", e.message);
  }
180 181

  return 0;
182
}