main.vala 4.58 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 12
  private OVCC.Player       player = null;
  private OVCCClient.Client client = null;
13 14
  private OVCCClient.Game   game   = null;
  public  OVCC.Network.SignalHandle signal_handle = null;
15 16
  
  public bool join (OVCCClient.Server server)
17
    throws Error
18
  {
19
    uint            player_suffix = 7;
20

21
    /* connect to the server */
22
    debug ("Trying to connect to server...");
23 24 25 26 27
    server.connect_to (); /* may throw a rejection */
    debug ("Connected");

    /* login to the server, choosing an available nickname */
    debug ("Trying to login...");
28 29
    do {
      /* Create our player instance */
30
      player = new OVCC.Player ("""Clever bot %03u""".printf (player_suffix));
31
      
32
      try {
33
        client = new OVCCClient.Client (player);
34
        server.login_to (player);
35
        break;
36
      } catch (OVCCClient.ServerError.NICKNAME_IN_USE e) {
37
        player_suffix++;
38
      } catch (OVCCClient.ServerError.MISSING_AUTHENTICATION e) {
39
        server.disconnect_from ();
40
        throw e; /* avoid infinite loop */
41 42 43
      } catch (Error e) {
        server.disconnect_from ();
        throw e;
44 45
      }
    }
46
    while (true);
47 48
    debug ("Logged in with player_suffix = %u", player_suffix);

49
    /* join any open table */
50
    debug ("Trying to join a table...");
51 52
    try {
      game = server.join_table (-1);
53
    } catch (Error e) {
54
      server.disconnect_from ();
55
      throw e;
56 57
    }
    debug ("Joined");
58 59 60

    /* start listening to the server */
    server.start_listening (game, player);
61
    
62 63 64 65 66 67 68 69 70 71 72 73 74
    /* react on game state changes */
    game.notify["state"].connect ((s, p) => {
      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;
      }
75 76
    });
    /* we should place a tile? OK, why not */
77
    client.place_tile.connect ((tile) => {
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
      debug ("Seems we should place a tile...");
      game.board.foreach ((b, p, t) => {
        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... */
            if (game.place_tile (player, npos)) {
              return false;
            } else {
              tile.rotate (1);
            }
          }
        }
        return true;
      });
    });
    /* we should place a pawn? let's do so */
102
    client.place_pawn.connect ((game, tile) => {
103 104 105 106 107
      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... */
108 109 110
//         if (game.place_pawn (player.pawns.nth_data (0), o)) {
//           break;
//         }
111 112
      }
    });
113 114

    return true;
115
  }
116 117 118 119 120
  
  public Bot (MainLoop l)
  {
    loop = l;
  }
121 122
}

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

#if HAVE_POSIX
private static void signal_handler (int sig)
{
  debug ("Caught signal %d, exiting", sig);
  try {
    server.disconnect_from ();
  } catch (Error e) {
    warning ("Error disconnecting from server: %s", e.message);
  }
  loop.quit ();
  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


MainLoop          loop    = null;
Bot               bot     = null;
OVCCClient.Server server  = null;

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

  return 0;
183
}