Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
428 lines (383 sloc) 11.1 KB
scilla_version 0
(* TicTacToe contract *)
import ListUtils
(***************************************************)
(* Associated library *)
(***************************************************)
library TicTacToe
let one_msg =
fun (msg : Message) =>
let nil_msg = Nil {Message} in
Cons {Message} msg nil_msg
let not_owner_code = Int32 1
let not_open_code = Int32 2
let full_slot_code = Int32 3
let same_owner_code = Int32 4
let busing_code = Int32 5
let set_joined_code = Int32 6
let no_challenger_code = Int32 7
let set_accepted_code = Int32 8
let set_refused_code = Int32 9
let set_closed_code = Int32 10
let wrong_turn_code = Int32 11
let move_code = Int32 12
let invalid_move_code = Int32 13
let same_status_code = Int32 14
let changed_status_code = Int32 15
let none_challenger = None {ByStr20}
let cell_empty = Uint32 0
let cell_x = Uint32 1
let cell_o = Uint32 2
let result_none = Uint32 0
let result_x = Uint32 1
let result_o = Uint32 2
let result_draw = Uint32 3
let zero = Uint32 0
let one = Uint32 1
let two = Uint32 2
let three = Uint32 3
let four = Uint32 4
let five = Uint32 5
let six = Uint32 6
let seven = Uint32 7
let eight = Uint32 8
let nine = Uint32 9
let is_same_bool =
fun (a: Bool) =>
fun (b: Bool) =>
match a with
| True =>
match b with
| True => True
| False => False
end
| False =>
match b with
| True => False
| False => True
end
end
let check_valid_move =
fun (bs : Map Uint32 Uint32) =>
fun (slot : Uint32) =>
let valid_right = builtin lt slot nine in
let c = builtin get bs slot in
match valid_right with
| True =>
match c with
| Some v =>
let compare = builtin eq v cell_empty in
match compare with
| True => True
| False => False
end
| None => False
end
| False => False
end
let cell_at =
fun (bs : Map Uint32 Uint32) =>
fun (i : Uint32) =>
let c = builtin get bs i in
match c with
| Some v => v
| None => cell_empty
end
let check_three_cell =
fun (l : Uint32) =>
fun (a : Uint32) =>
fun (b : Uint32) =>
fun (c : Uint32) =>
let comparel = builtin eq l result_none in
match comparel with
| False => l
| True =>
let compareab = builtin eq a b in
let comparebc = builtin eq b c in
let compareax = builtin eq a cell_x in
let compareao = builtin eq a cell_o in
match compareab with
| True =>
match comparebc with
| True =>
match compareax with
| True => result_x
| False =>
match compareao with
| True => result_o
| False => result_none
end
end
| False => result_none
end
| False => result_none
end
end
let get_winner_code =
fun (bs : Map Uint32 Uint32) =>
fun (t : Uint32) =>
let is_last_turn = builtin lt seven t in
let at_0 = cell_at bs zero in
let at_1 = cell_at bs one in
let at_2 = cell_at bs two in
let at_3 = cell_at bs three in
let at_4 = cell_at bs four in
let at_5 = cell_at bs five in
let at_6 = cell_at bs six in
let at_7 = cell_at bs seven in
let at_8 = cell_at bs eight in
let ret0 = result_none in
let ret1 = check_three_cell ret0 at_0 at_1 at_2 in
let ret2 = check_three_cell ret1 at_3 at_4 at_5 in
let ret3 = check_three_cell ret2 at_6 at_7 at_8 in
let ret4 = check_three_cell ret3 at_0 at_3 at_6 in
let ret5 = check_three_cell ret4 at_1 at_4 at_7 in
let ret6 = check_three_cell ret5 at_2 at_5 at_8 in
let ret7 = check_three_cell ret6 at_0 at_4 at_8 in
let ret8 = check_three_cell ret7 at_2 at_4 at_6 in
let comparel = builtin eq ret8 result_none in
match comparel with
| False => ret8
| True =>
match is_last_turn with
| False => result_none
| True => result_draw
end
end
let new_board =
let bs : Map Uint32 Uint32 = Emp Uint32 Uint32 in
let b0 = builtin put bs zero cell_empty in
let b1 = builtin put b0 one cell_empty in
let b2 = builtin put b1 two cell_empty in
let b3 = builtin put b2 three cell_empty in
let b4 = builtin put b3 four cell_empty in
let b5 = builtin put b4 five cell_empty in
let b6 = builtin put b5 six cell_empty in
let b7 = builtin put b6 seven cell_empty in
let b8 = builtin put b7 eight cell_empty in
b8
let get_turn_addr =
fun (t : Uint32) =>
fun (h : ByStr20) =>
fun (cl : Option ByStr20) =>
let m = builtin rem t two in
let compare = builtin eq m one in
match compare with
| True =>
match cl with
| Some v => v
| None => h
end
| False => h
end
let next_turn =
fun (t : Uint32) =>
builtin add t one
let turn_cell =
fun (t : Uint32) =>
let m = builtin rem t two in
let compare = builtin eq m one in
match compare with
| False => cell_x
| True => cell_o
end
(***************************************************)
(* The contract definition *)
(***************************************************)
contract TicTacToe
(owner: ByStr20,
checksum: String)
field opening : Bool = False
field accepted : Bool = False
field challenger : Option ByStr20 = None {ByStr20}
field welcome_msg : String = ""
field board : Map Uint32 Uint32 = Emp Uint32 Uint32
field moves : List Uint32 = Nil {Uint32}
field turn : Uint32 = zero
field winner_code : Uint32 = result_none
transition join (mess: String)
is_owner = builtin eq owner _sender;
is_opening <- opening;
is_accepted <- accepted;
cl <- challenger;
match is_opening with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_open_code};
msgs = one_msg msg;
send msgs
| True =>
match is_accepted with
| True =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : busing_code};
msgs = one_msg msg;
send msgs
| False =>
match is_owner with
| True =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : same_owner_code};
msgs = one_msg msg;
send msgs
| False =>
match cl with
| Some v =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : full_slot_code};
msgs = one_msg msg;
send msgs
| None =>
sc = Some {ByStr20} _sender;
challenger := sc;
welcome_msg := mess;
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : set_joined_code};
msgs = one_msg msg;
send msgs
end
end
end
end
end
transition answerChallenge (b: Bool)
is_owner = builtin eq owner _sender;
is_opening <- opening;
is_accepted <- accepted;
cl <- challenger;
match is_opening with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_open_code};
msgs = one_msg msg;
send msgs
| True =>
match is_accepted with
| True =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : busing_code};
msgs = one_msg msg;
send msgs
| False =>
match is_owner with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_owner_code};
msgs = one_msg msg;
send msgs
| True =>
match cl with
| None =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : no_challenger_code};
msgs = one_msg msg;
send msgs
| Some v =>
match b with
| False =>
tt = False;
accepted := tt;
nc = None {ByStr20};
challenger := nc;
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : set_closed_code};
msgs = one_msg msg;
send msgs
| True =>
tt = True;
accepted := tt;
turn := zero;
winner_code := zero;
nb = new_board;
board := nb;
m = Nil {Uint32};
moves := m;
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : set_accepted_code};
msgs = one_msg msg;
send msgs
end
end
end
end
end
end
transition changeOpenStatus (b: Bool)
is_owner = builtin eq owner _sender;
is_opening <- opening;
is_same_status = is_same_bool is_opening b;
match is_same_status with
| True =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : same_status_code};
msgs = one_msg msg;
send msgs
| False =>
match is_owner with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_owner_code};
msgs = one_msg msg;
send msgs
| True =>
opening := b;
tt = False;
accepted := tt;
nc = None {ByStr20};
challenger := nc;
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : changed_status_code};
msgs = one_msg msg;
send msgs
end
end
end
transition move (slot : Uint32)
is_owner = builtin eq owner _sender;
t <- turn;
cl <- challenger;
turn_addr = get_turn_addr t owner cl;
is_correct_turn = builtin eq turn_addr _sender;
is_opening <- opening;
is_accepted <- accepted;
bs <- board;
is_valid_move = check_valid_move bs slot;
tc = turn_cell t;
match is_opening with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_open_code};
msgs = one_msg msg;
send msgs
| True =>
match cl with
| None =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : no_challenger_code};
msgs = one_msg msg;
send msgs
| Some v =>
match is_correct_turn with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : invalid_move_code};
msgs = one_msg msg;
send msgs
| True =>
match is_valid_move with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : invalid_move_code};
msgs = one_msg msg;
send msgs
| True =>
bs1 = builtin remove bs slot;
bs2 = builtin put bs slot tc;
board := bs2;
m <- moves;
mn = Cons {Uint32} slot m;
moves := mn;
nt = next_turn t;
turn := nt;
wc = get_winner_code bs2 t;
is_not_end = builtin eq wc result_none;
match is_not_end with
| True =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : move_code};
msgs = one_msg msg;
send msgs
| False =>
winner_code := wc;
tt = False;
opening := tt;
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : move_code};
msgs = one_msg msg;
send msgs
end
end
end
end
end
end