Newer
Older
Octopus_Carnival / hosaka / cards.ml
Francesco Mecca on 19 Aug 2019 3 KB see todo
open List;;

(* Random.self_init ();;  *)

type card_type =
  | Hearts 
  | Tiles 
  | Clovers 
  | Pikes
  | Nothing

let card_type_to_string = function 
  | Hearts -> "Hearts"
  | Tiles -> "Tiles"
  | Clovers -> "Clovers"
  | Pikes-> "Pikes"
  | Nothing-> "Nothing"

let string_to_card_type = function 
  | "Hearts" -> Hearts
  | "Tiles" -> Tiles
  | "Clovers" -> Clovers
  | "Pikes" -> Pikes
  | "Nothing" -> Nothing
  | _ -> assert false

type card = { seed: card_type ; value: int }

let make seed value =
  { seed=seed; value=value }

let value_cmp a b = if a.value < b.value then -1 else if a.value = b.value then 0 else 1 (* TFW TODO *)
let seed_cmp = fun a b -> if card_type_to_string a.seed > card_type_to_string b.seed then 1 else
    if card_type_to_string a.seed = card_type_to_string b.seed then 0 else -1

let make_set tp =
  let rec range start _end accum = if start < _end then range (start+1) _end accum@[start]  else accum in
  List.map (fun x -> { seed=tp; value=x }) (range 1 14 []);; (* make a set of cards of one seed *)
let init = 
  List.concat [make_set Hearts ; make_set Tiles ; make_set Clovers ; make_set Pikes ;
               make_set Hearts ; make_set Tiles ; make_set Clovers ; make_set Pikes] |>
  List.map (fun e -> Random.bits (), e) |>
  List.sort (fun a b -> if fst a > fst b then 1 else -1)  |>
  List.map snd 

let draw deck = match deck with
    | [] as l -> {seed=Nothing ; value=0}, l
    | hd::tl -> hd, tl

let no_double_seed cards =
  List.sort_uniq seed_cmp cards |> List.length = List.length cards

let is_only_one_seed cards =
  List.sort_uniq seed_cmp cards |> List.length = 1

let no_double_value cards =
  List.sort_uniq value_cmp cards |> List.length = List.length cards

let is_tris cards =
  match (List.sort_uniq value_cmp cards)  with
  | [_] -> no_double_seed cards (* only one value, check for right seeds *)
  | _::_ -> false
  | [] -> assert false

let rec split l fst =
  match l with
  | hd::hd'::tl when hd=hd'-1 -> split (hd'::tl) (fst@[hd])
  | hd::tl -> fst@[hd], tl
  | [] -> assert false


let is_straight _cards =
  let rec _is_straight cards =
    match cards with
    | hd::hd'::tl when hd=hd'-1 -> _is_straight (hd'::tl)
    | [] -> assert false
    | [_] -> true (* list was consumed *)
    | _::_ -> false in

  if (not (no_double_value _cards && is_only_one_seed _cards)) then
    false
  else
    let ocards = List.sort value_cmp _cards  in
    let last = List.rev ocards |> hd in
    let cards  = List.map (fun c -> c.value) ocards (* use only values *) in
    if last.value = 13 && (hd cards) = 1 then (* circolare *)
      let fst, snd = split cards [] in (_is_straight fst) && (_is_straight snd)
    else
      (* let res = _is_straight cards in
       * List.iter (fun c -> Printf.printf "%d:%s - " c.value (card_type_to_string c.seed)) _cards ; Printf.printf "%b\n" res;
       * res *) (* TODO : remove *)
      _is_straight cards

let is_valid _cards =
  let cards = List.sort value_cmp _cards in
  if List.length cards < 3 then
    false
  else
    match cards with
    | a::b::_ when value_cmp a b = 0  -> is_tris cards
    | _ -> is_straight cards;;