aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex AUVOLAT <alex.auvolat@ens.fr>2014-11-09 01:07:08 +0100
committerAlex AUVOLAT <alex.auvolat@ens.fr>2014-11-09 01:07:08 +0100
commit671244fc96a54dff2d3bec618ec9e398f744e430 (patch)
tree1139550f1355cf9050bfcabf83c30846ceb93264
parent65af3ed6ef638ea46229bd64c1a10cec3e5a34d8 (diff)
downloadCompetIA-671244fc96a54dff2d3bec618ec9e398f744e430.tar.gz
CompetIA-671244fc96a54dff2d3bec618ec9e398f744e430.zip
Improve judge, add NiAh player from AP.
-rw-r--r--.gitignore1
-rw-r--r--judge/core.ml106
-rw-r--r--morpion_rec/NiAh/main.c243
-rw-r--r--morpion_rec/NiAh/main.h13
4 files changed, 362 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 262dedf..b3bc943 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ judge/_build/*
*.native
*.byte
+morpion_rec/*/player
diff --git a/judge/core.ml b/judge/core.ml
index 7012118..65a43a8 100644
--- a/judge/core.ml
+++ b/judge/core.ml
@@ -62,9 +62,12 @@ end
module C (G: GAME) : CORE = struct
module G : GAME = G
+ exception Eliminated_ex
+
type player = {
name: string;
binary: string;
+ log_out: file_descr;
mutable score: int;
}
@@ -151,9 +154,15 @@ module C (G: GAME) : CORE = struct
if (st.st_kind = S_REG || st.st_kind = S_LNK)
&& (st.st_perm land 0o100 <> 0) then begin
Format.printf "- %s@." s;
+ (* open log output for player *)
+ let p_log_file = Filename.concat (Filename.concat !game_dir s) "stderr.log" in
+ let p_log_out = Unix.openfile p_log_file [O_APPEND; O_CREAT; O_WRONLY] 0o644 in
+ let f = Format.formatter_of_out_channel (out_channel_of_descr p_log_out) in
+ Format.fprintf f "---- Begin session %s@." date;
Hashtbl.add players s
{ name = s;
binary = b;
+ log_out = p_log_out;
score = 0; }
end
with _ -> ();
@@ -179,12 +188,15 @@ module C (G: GAME) : CORE = struct
Format.printf "Launching match: %s vs. %s@." p1 p2;
let open_c p =
+ let f =Format.formatter_of_out_channel (out_channel_of_descr p.log_out) in
+ Format.fprintf f "--- Begin game (%s vs. %s)@." p1 p2;
let (j2p_i, j2p_o) = pipe () in
let (p2j_i, p2j_o) = pipe () in
let pid = fork() in
if pid = 0 then begin
dup2 j2p_i stdin;
dup2 p2j_o stdout;
+ dup2 p.log_out stderr;
execv p.binary [| p.binary |];
end;
Format.printf "- %s: pid %d@." p.name pid;
@@ -204,6 +216,98 @@ module C (G: GAME) : CORE = struct
(* 2. LOOK IF ANYBODY IS TELLING US SOMETHING - IF SO, REACT
(wait max. 0.01 sec) *)
- ()
+ let in_fd = List.fold_left
+ (fun l g -> match g.s with
+ | Finished _ -> l
+ | _ ->
+ let l = match g.p1.s with
+ | Dead -> l
+ | _ -> (Unix.descr_of_in_channel g.p1.i)::l
+ in match g.p2.s with
+ | Dead -> l
+ | _ -> (Unix.descr_of_in_channel g.p2.i)::l)
+ [] !r_games
+ in
+ let in_fd, _, _ = select in_fd [] [] 0.01 in
+ let do_fd fd =
+ let g = List.find
+ (fun g -> fd = Unix.descr_of_in_channel g.p1.i
+ || fd = Unix.descr_of_in_channel g.p2.i)
+ !r_games
+ in
+ let pi = if Unix.descr_of_in_channel g.p1.i = fd then P1 else P2 in
+ let p = match pi with P1 -> g.p1 | P2 -> g.p2 in
+ let op = match pi with P1 -> g.p2 | P2 -> g.p1 in
+ begin try match decode (input_line p.i), p.s with
+ | Hello x, Loading when x = G.id ->
+ p.s <- StandBy !game_time;
+ if op.s <> Loading then begin
+ match g.s, g.p1.s, g.p2.s with
+ | Initializing (TurnOf P1), StandBy t, _ ->
+ send_m g.p1 (YourTurn t);
+ g.p1.s <- Thinking (t, Unix.time());
+ g.s <- Running (TurnOf P1)
+ | Initializing (TurnOf P2), _, StandBy t ->
+ send_m g.p2 (YourTurn t);
+ g.p2.s <- Thinking (t, Unix.time());
+ g.s <- Running (TurnOf P2)
+ | _ -> assert false
+ end
+ | Play act, Thinking (time, beg_r) ->
+ let end_r = Unix.time () in
+ let new_s = G.turn g.g pi act in
+ begin match new_s with | Eliminated _ -> raise Eliminated_ex | _ -> () end;
+ send_m p OK;
+ send_m op (Play act);
+ let finished = match new_s with
+ | Tie ->
+ send_m p Tie;
+ send_m op Tie;
+ Format.printf "%s vs. %s: tie!@." g.p1.p.name g.p2.p.name;
+ true
+ | Won x when x = pi ->
+ send_m p YouWin;
+ send_m op YouLose;
+ Format.printf "%s vs. %s: %s wins!@." g.p1.p.name g.p2.p.name p.p.name;
+ true
+ | Won x ->
+ send_m op YouWin;
+ send_m p YouLose;
+ Format.printf "%s vs. %s: %s wins!@." g.p1.p.name g.p2.p.name op.p.name;
+ true
+ | TurnOf _ -> false
+ | Eliminated x -> assert false
+ in
+ if finished then begin
+ p.s <- Saving;
+ op.s <- Saving;
+ g.s <- Finished new_s
+ end else begin
+ p.s <- StandBy (time -. (end_r -. beg_r));
+ g.s <- Running new_s;
+ match op.s with
+ | StandBy t ->
+ send_m op (YourTurn t);
+ op.s <- Thinking (t, Unix.time())
+ | _ -> assert false
+ end
+ | FairEnough, Saving ->
+ kill p.pid 15; (* 15 : sigterm *)
+ p.s <- Dead
+ | _ -> raise Eliminated_ex
+ | exception _ -> raise Eliminated_ex
+ with
+ | Eliminated_ex ->
+ send_m p Eliminated;
+ send_m op YouWin;
+ (* since process is not respecting the protocol, we cannot assume
+ it is doing anything reasonable, so we kill it... *)
+ kill p.pid 15;
+ Format.printf "%s vs. %s: %s eliminated!@." g.p1.p.name g.p2.p.name p.p.name;
+ p.s <- Dead;
+ op.s <- Saving;
+ g.s <- Finished (Eliminated pi)
+ end;
+ in List.iter do_fd in_fd
end
diff --git a/morpion_rec/NiAh/main.c b/morpion_rec/NiAh/main.c
new file mode 100644
index 0000000..74248c3
--- /dev/null
+++ b/morpion_rec/NiAh/main.c
@@ -0,0 +1,243 @@
+/* IA pour morpion récursif - Alexis
+ * main.c
+ * Contient les fonctions principales */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "main.h"
+
+#define INPUT_LENGTH 50
+
+int main()
+{
+ int i,j,k,l;
+
+ char input[INPUT_LENGTH];
+ float timeout;
+
+ Dots grid[9][9];
+ Boxes subgrid, move, firstsubgrid;
+ int firstMove=1;
+
+ for(i=0;i<9;i++)
+ for(j=0;j<9;j++)
+ grid[i][j] = FREE;
+
+ subgrid = Z;
+ firstsubgrid=V;
+
+ // Dis bonjour à Alex ...
+ fgets(input, sizeof(input), stdin);
+ for(i=0;i<INPUT_LENGTH;i++){if(input[i]=='\n'){input[i]='\0';}}
+ if(strcmp(input, "Hello morpion_rec") == 0)
+ {
+ printf("Hello morpion_rec\n");
+ }
+ else
+ {
+ printf("Who are you, crazy bastard?\n");
+ return EXIT_FAILURE;
+ }
+
+ printGrid(grid);
+
+ // Est-ce à moi de jouer ?
+ while(1)
+ {
+ while(1)
+ {
+ fgets(input, sizeof(input), stdin);
+
+ // Attendre pour jouer
+ if(strstr(input,"Your turn")==input)
+ {
+ sscanf(input+10,"%f",&timeout);
+ break;
+ }
+
+ //Attendre le coup de l'adversaire
+ if(strstr(input,"Play")==input)
+ {
+ sscanf(input+5,"%d %d %d %d",&i,&j,&k,&l);
+ subgrid=(i-1)+(j-1)*3;
+ move = (k-1)+(l-1)*3;
+ fprintf(stderr,"%d %d\n", subgrid, move);
+ // L'adversaire joue les ronds
+ if(firstMove)
+ {
+ firstsubgrid=subgrid;
+ firstMove=0;
+ }
+ play(grid, subgrid, CIRCLE, move);
+ printGrid(grid);
+ subgrid=move;
+ }
+
+ // Attendre le résultat de la partie
+ if(strstr(input,"You win")==input)
+ {
+ printf("Yeah!");
+ return EXIT_SUCCESS;
+ }
+ if(strstr(input,"You lose")==input)
+ {
+ printf("I am so sad...");
+ return EXIT_SUCCESS;
+ }
+ if(strstr(input,"Tie")==input)
+ {
+ printf("It is a good result anyways.");
+ return EXIT_SUCCESS;
+ }
+ if(strstr(input,"Cheater")==input)
+ {
+ printf("You are so nasty :(");
+ return EXIT_FAILURE;
+ }
+
+ }
+
+ // On joue toujours les croix
+ if(firstMove)
+ {
+ firstsubgrid=V;
+ subgrid=firstsubgrid;
+ firstMove=0;
+ }
+ if(chooseMoveAndPlay(grid, subgrid, CROSS, &move, firstsubgrid) != 0){return EXIT_FAILURE;}
+ printf("Play %d %d %d %d\n", subgrid%3+1, subgrid/3+1, move%3+1, move/3+1);
+
+ subgrid=move;
+ printGrid(grid);
+ }
+
+
+ return EXIT_SUCCESS;
+}
+
+int play(Dots grid[9][9], Boxes subgrid, Dots player, Boxes move)
+{
+ if(subgrid == Z || move == Z || player == FREE || grid[subgrid][move] != FREE)
+ return 1;
+ grid[subgrid][move] = player;
+}
+
+int chooseMoveAndPlay(Dots grid[9][9], Boxes subgrid, Dots player, Boxes *move, Boxes firstSubgrid)
+{
+ int i,j;
+ Boxes sg = (subgrid!=Z) ? subgrid : V; // Inutile maintenant
+ for(i=0;i<9;i++)
+ {
+ if(grid[sg][i] == FREE)
+ {
+ *move = i;
+ grid[sg][i] = player;
+ return 0;
+ }
+ }
+ if(firstSubgrid=subgrid)
+ {
+ for(i=0;i<9;i++)
+ {
+ for(j=0;j<9;j++)
+ {
+ if(grid[j][i] == FREE)
+ {
+ *move = i;
+ grid[j][i] = player;
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+void checkSolutions(Boxes a, Solutions sols)
+{
+ switch(a)
+ {
+ case I:
+ sols[0][0] = II; sols[0][1] = III;
+ sols[1][0] = IV; sols[1][1] = VII;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ case II:
+ sols[0][0] = I; sols[0][1] = III;
+ sols[1][0] = V; sols[1][1] = VIII;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ case III:
+ sols[0][0] = I; sols[0][1] = II;
+ sols[1][0] = VI; sols[1][1] = IX;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ case IV:
+ sols[0][0] = I; sols[0][1] = VII;
+ sols[1][0] = V; sols[1][1] = VI;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ case V:
+ sols[0][0] = II; sols[0][1] = VIII;
+ sols[1][0] = I; sols[1][1] = IX;
+ sols[2][0] = IV; sols[2][1] = VI;
+ sols[3][0] = VII; sols[3][1] = III;
+ break;
+ case VI:
+ sols[0][0] = IV; sols[0][1] = V;
+ sols[1][0] = III; sols[1][1] = IX;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ case VII:
+ sols[0][0] = I; sols[0][1] = IV;
+ sols[1][0] = VII; sols[1][1] = IX;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ case VIII:
+ sols[0][0] = II; sols[0][1] = V;
+ sols[1][0] = VI; sols[1][1] = IX;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ case IX:
+ sols[0][0] = III; sols[0][1] = VI;
+ sols[1][0] = VII; sols[2][1] = IX;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ default:
+ sols[0][0] = Z; sols[0][1] = Z;
+ sols[1][0] = Z; sols[1][1] = Z;
+ sols[2][0] = Z; sols[2][1] = Z;
+ sols[3][0] = Z; sols[3][1] = Z;
+ break;
+ }
+}
+
+// Les affichages se font dans stderr
+void printGrid(Dots grid[9][9])
+{
+ int x,y, i,j;
+
+ fprintf(stderr,"\n*********\n");
+ for(x=0;x<9;x++)
+ {
+ for(y=0;y<9;y++)
+ {
+ i=(y/3)*3+(x/3);
+ j=(y-(y/3)*3)*3+(x-(x/3)*3);
+ fprintf(stderr,"%d", grid[i][j]);
+ }
+ fprintf(stderr,"\n");
+ }
+ fprintf(stderr,"\n*********\n");
+}
+
+
diff --git a/morpion_rec/NiAh/main.h b/morpion_rec/NiAh/main.h
new file mode 100644
index 0000000..5cf06d2
--- /dev/null
+++ b/morpion_rec/NiAh/main.h
@@ -0,0 +1,13 @@
+/* IA pour morpion récursif - Alexis
+ * main.h
+ * Définition des énumérations, typedef et autres */
+
+typedef enum {FREE, CROSS, CIRCLE} Dots;
+typedef enum {I=0, II=1, III=2, IV = 3, V=4, VI=5, VII=6, VIII=7, IX=8, Z=-1} Boxes;
+typedef Boxes Solutions[4][2];
+
+int play(Dots grid[9][9], Boxes subgrid, Dots player, Boxes move);
+int chooseMoveAndPlay(Dots grid[9][9], Boxes subgrid, Dots player, Boxes *move, Boxes firstSubgrid);
+void checkSolutions(Boxes a, Solutions sols);
+void printGrid(Dots grid[9][9]);
+