Valid XHTML 1.0 Transitional

Last modified: Mon May 17 14:44:55 CEST 2004

IF242 : logique et circuits

2003-2004

Page ocaml : conseils, code, etc.

Correction du TD5

Correction du projet

Un corrigé du projet.

Transformation en jeu

Pour ceux qui seraient tentés de continuer, une idée serait de transformer le jeu en course de voitures multi-joueurs dans un labyrinthe. La partie course est tirée du concours de l'ICFP 2003 (International Conference on Functional Programming). Site du concours.

En fait, cela combine labyrinthe et simulation de course. Pour la partie simulation, on part d'équation physique du mouvement qui permette de connaître la position à l'instant suivant en fonction de l'état précédent et d'une commande.

Les commandes possibles sont :

type action = Roll | Acc | Left | Right | Brake | AccLeft | AccRight
      

Par rapport à ce qu'on a vu jusqu'à maintenant, il est pratique d'utiliser des types structurés pour modéliser l'état d'un véhicule à un instant donné :

type state = {
x : t ; (* position *)
y : t ; (* position *)
v : t ; (* impulsion *)
d : t ; (* angle *)
t : t (* temps *)
}
      

Remarque : t est un type prédéfini, par exemple float. Dans le cas du concours, il fallait utiliser de l'arithmétique en point fixe, et c'est ce code qui est toujours utilisé (toutes les fonctions de calcul, similaires au float, sont définies dans fpa.ml). C'était plus une contrainte qu'autre chose (pour éviter que quelqu'un ne propose une solution analytique à leur problème : il s'agissait de trouver la séquence de commande la plus rapide sur divers circuits proposés), et il vaut mieux travailler en float.

Il existe deux modes de simulation : un normal, et un "rally" qui autorise les dérapages.

(** normal *)
let next s ac =
  let v = s.v -. (f0 +. f1 *. s.v +. f2 *. (s.v *. s.v)) in
  let v = max zero (match ac with
		      `Acc | `AccLeft | `AccRight -> v +. biga
		    | `Brk -> (v -. bigb)
		    | _ -> v) in
  let d = match ac with
    `Left | `AccLeft -> s.d -. (bigt /. (v *. v +. bigl))
  | `Right | `AccRight -> s.d +. (bigt /. (v *. v +. bigl)) 
  | _ -> s.d in
  let d = bonmod d in
  let x = s.x +. (v *. cos d)
  and y = s.y +. (v *. sin d) in
  { v = v ; d = d ; t = d ; x = x ; y = y }

(** rally *)
let next_r s ac =
  let v = ref s.v
  and t = ref s.t
  and d = ref s.d
  and x = ref s.x
  and y = ref s.y
  and turn = ref zero
  and diff = ref zero
  and return = ref false
  in
  turn := (bigt /. ((!v *. !v) +. bigl)) ;
  diff := anglediff !t !d ;
  if abs !diff < !turn || !v = zero then t := !d ;
  v := !v -. (f0 +. f1 *. !v +. f2 *. (!v *. !v)) ;
  let skid = 
    if t <> d then true
    else derape ac
  in
  if skid then (
    turn := ((of_int 2) *: bigt) /. bigl ;
    if not (accel ac) then v := !v -. bskid ;
    if !v < zero then ( v := zero ; t := !d ; return := true) 
    else
      if accel ac then
	let vx = (!v *. cos !t) +. (askid *. cos !d) 
	and vy = (!v *. sin !t) +. (askid *. sin !d) in
	v := sqrt ((vx *. vx) +. (vy *. vy)) ;
	t := atan2 vy vx ;
	if (anglediff !t !d) *. !diff < zero && abs !diff < pisur2 then t := !d
  ) else (
    if accel ac then v := !v +. biga ;
    if brake ac then v := !v -. bigb ;
    if !v < zero then v := zero ;
    turn := bigt /. ((!v *. !v) +. bigl)
  ) ;
  if not !return then (
    if left ac then d := !d -. !turn ;
    if right ac then d := !d +. !turn ;
    d := bonmod (!d) ;
    x := !x +. (!v *. cos !t) ;
    y := !y +. (!v *. sin !t) 
  ) ;
  if not skid then t := !d ;
  { x = !x ;
    y = !y ;
    v = !v ;
    d = !d ;
    t = !t
  }
	    

Le code

Vous pouvez télécharger le tout début. Pour l'instant, cela ne marche pas encore, c'est juste une base de départ pour vous permettre de démarrer plus rapidement.

Ce code utilise notamment quelques notions qui n'ont pas été abordées en cours :

<