
type pos = int;

node succ(x: pos) returns (y: pos);
let
	y = (x + 1) mod 4;
tel

type tab = pos^3^3;

node ba_all(const n : int; I : bool^n) returns ( ok : bool);
var
   All : bool^n;
let
   All = [I[0]] | ( All[0..n-2] and I[1..n-1]);
   ok = All[n-1];
tel
node zero_cell(x:int) returns (z: bool); 
let
	z = (x=0);
tel
node zero_line(l:int^3) returns (z: bool);
let
	z = ba_all(3, zero_cell(l));
tel
node zero_tab(t:int^3^3) returns (z: bool);
let
	z = ba_all(3, zero_line(t));
tel


unsafe function random_int(min,max:int)returns(alea:int);

node neighbor(x: bool^3^3) returns (n: bool^3^3);
let
   n[0] = x[0] or x[1] or         ([false]|x[0][0..1]) or (x[0][1..2]|[false]);
   n[1] = x[0] or x[1] or x[2] or ([false]|x[1][0..1]) or (x[1][1..2]|[false]);
   n[2] = x[1] or x[2] or         ([false]|x[2][0..1]) or (x[2][1..2]|[false]);
tel

node game (c: bool^3^3; start: bool) returns (x: tab; win: bool);
var px: tab;
    nc: bool^3^3;
    rtab: int^3^3 when start;
let
	rtab = ((random_int(0,3))^3^3) when start;
   px = 0^3^3 -> pre x;
   nc = neighbor(c);
   x = if start then current rtab
	    else if nc then succ(px)
	    else px;
	win = zero_tab(x);
tel
