Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- let time_limit = 100;;
- let max_rating = 20;;
- let mem_size = 10;; (* четное число! *)
- class weapon (r0:int) (d0:int) =
- object
- val rng = r0
- val dmg = d0
- method get_dmg (r:int) = max ((Random.int dmg) + (Random.int dmg)-abs(r-rng)) 0
- (*let rec base_dmg x a =
- if x = 0 then a
- else base_dmg (x-1) (a +(Random.int 2)) in
- base_dmg (2*d0 - abs(rng-r)) 0*)
- method get_rng = rng
- end;;
- type act = StepF | StepB | Wait | Hit of weapon;;
- type t_ai = (act*(float list)) list * int;;
- let mutation l rt=
- let deep = min ((1.1 -. (float_of_int rt)/.(float_of_int max_rating))/.2.) 1.0 in
- List.map (fun (act,w) -> act,
- (List.map (fun f->f*.(1.-.deep+.Random.float deep)) w)
- ) l;;
- class hero nm xp0 tactics0=
- object(s)
- val name:string = nm
- val max_xp = xp0
- val mutable xp = xp0
- val mutable wps = []
- val mutable tactics = Array.make mem_size (tactics0,0)
- val mutable act_tack = 0
- method respawn = xp<-max_xp
- method get_name = name
- method get_xp = xp
- method add_wp wp tack = wps <- wp::wps;
- tactics<-Array.map (fun (ai_lt,rt)-> (Hit wp,tack)::ai_lt,rt) tactics
- method drop_all = wps <- []
- method beaten r d = xp <- xp-d +(r*0)
- method renew_tactics =
- Array.sort (fun (_,r1) (_,r2) -> r2-r1) tactics;
- for i=0 to mem_size/2 - 1 do
- let ai,rt = tactics.(i) in
- tactics.(i) <- ai,0;
- (* мутации! мутации! *)
- tactics.(i+mem_size/2) <- (mutation ai rt,0)
- done
- method rate i =
- let (ai,rt) = tactics.(act_tack) in
- tactics.(act_tack) <- (ai,rt+i);
- act_tack <- (act_tack+1) mod mem_size;
- if abs(rt+i) > max_rating then s#renew_tactics
- method choose env =
- let mult (act,w) =
- List.fold_left2
- (fun (name,accum) f i -> name,(accum +. f *. (float_of_int i)))
- (act,0.) w env in
- let results = List.map mult (fst tactics.(act_tack)) in
- let decreasing = List.fast_sort (fun (_,f1) (_,f2) -> if f1>f2 then -1 else 1) results in
- fst(List.split decreasing)
- method get_wp_rng = (List.hd wps)#get_rng
- method print_tactics =
- for i =0 to mem_size-1 do
- let (ai,rt) = tactics.(i) in
- Printf.printf "\nTactics #1, rating %i:" rt;
- List.iter (fun (act,l)-> begin match act with
- |StepF -> Printf.printf "\n\tF ->\t"
- |StepB -> Printf.printf "\n\tB ->\t"
- |Wait -> Printf.printf "\n\tW ->\t"
- |Hit _ -> Printf.printf "\n\tH ->\t"end;
- List.iter (fun f->Printf.printf "%2.3f\t" f) l)
- ai
- done
- initializer
- for i=0 to mem_size - 1 do
- let ai,_ = tactics.(i) in
- (* мутации! мутации! *)
- tactics.(i) <- (mutation ai (max_rating/2),0)
- done
- end;;
- (* env: xp, dist, self range, opp range *)
- let print_fight (hero0:hero) (hero1:hero) dist act sente =
- let h0,h1 = if sente then hero0,hero1
- else hero1,hero0 in
- print_string "@/";
- for i=0 to dist-2 do print_char '_' done;
- print_endline "\@";
- Printf.printf "%2i" h0#get_xp;
- for i=0 to dist-2 do print_char '_' done;
- Printf.printf "%2i" h1#get_xp; print_newline ();
- match act with
- |StepF -> Printf.printf "Hero \"%s\" steps forward.\n" hero0#get_name
- |StepB -> Printf.printf "Hero \"%s\" steps backward.\n" hero0#get_name
- |Wait -> Printf.printf "Hero \"%s\" is waiting.\n" hero0#get_name
- |Hit _ -> Printf.printf "Hero \"%s\" hits hero \"%s\".\n" hero0#get_name hero1#get_name
- |_ -> Printf.printf "Wrong action!!!\n";;
- let rec fight (hero0:hero) (hero1:hero) pos0 pos1 sente t draw =
- if hero0#get_xp <= 0 then begin hero0#rate (-1); hero1#rate 1; end
- else
- begin
- if t > time_limit then begin hero0#rate (-1); hero1#rate (-1); end
- else
- begin
- let dist = abs(pos1-pos0) in
- let actions = hero0#choose
- [hero0#get_xp;dist;hero0#get_wp_rng;hero1#get_wp_rng] in
- let rec pr = function
- | StepF::tl -> print_string "F "; pr tl
- | StepB::tl -> print_string "B "; pr tl
- | Wait ::tl -> print_string "W "; pr tl
- | (Hit _)::tl -> print_string "H "; pr tl
- | _ -> print_newline (); in
- (*pr actions;*)
- let rec get_av_act = function
- | StepF::tl -> if dist>2 then StepF else get_av_act tl
- | hd::tl -> hd in
- let action = get_av_act actions in
- if draw then print_fight hero0 hero1 dist action sente else ();
- match action with
- | StepF -> fight hero1 hero0 pos1 (pos0+2*(pos1-pos0)/dist) (not sente) (t+1) draw
- | StepB -> fight hero1 hero0 pos1 (pos0-1*(pos1-pos0)/dist) (not sente) (t+1) draw
- | Wait -> fight hero1 hero0 pos1 pos0 (not sente) (t+1) draw
- | Hit w -> begin hero1#beaten dist (w#get_dmg dist);
- fight hero1 hero0 pos1 pos0 (not sente) (t+1) draw end
- end
- end;;
- let main =
- Random.self_init ();
- let wp0 = new weapon ((Random.int 3)+2) (Random.int 15) in
- let wp1 = new weapon ((Random.int 3)+2) (Random.int 15) in
- let wp_tack0 = [0.1;0.1;0.1;0.1] in
- let wp_tack1 = List.map (fun f->0.1+.(Random.float f)) [1.;1.;1.;1.] in
- (* болванчик *)
- let ai0 = (StepF, [0.1;0.1;0.1;0.1])
- :: (StepB, [0.1;0.1;0.1;0.1])
- :: (Wait, [1.;0.1;0.1;0.1]):: [] in
- let ai1 = (StepF, List.map (fun f->0.1+.Random.float f) [1.;1.;1.;1.])
- :: (StepB, List.map (fun f->Random.float f) [1.;1.;1.;1.])
- :: (Wait, List.map (fun f->Random.float f) [1.;1.;1.;1.])
- :: [] in
- let sparrer = new hero "Sparrer" 20 ai0 in
- sparrer#add_wp wp0 wp_tack0;
- let the_one = new hero "The One" 20 ai1 in
- the_one#add_wp wp1 wp_tack1;
- for it = 0 to 3524 do
- fight the_one sparrer 0 20 true 0 false;
- the_one#respawn;
- sparrer#respawn;
- done;
- fight the_one sparrer 0 20 true 0 true;
- the_one#print_tactics;
- exit (0);;
- let _ = main ()
Add Comment
Please, Sign In to add comment