---
 src/lessons/lander/Main.fr.html                                                |   23 
 src/lessons/lander/Main.html                                                   |   21 
 src/lessons/lander/Main.scala                                                  |   14 
 src/lessons/lander/icon.svg                                                    |  104 ----
 src/lessons/lander/lvl1_lander_101/Lander101.fr.html                           |   49 -
 src/lessons/lander/lvl1_lander_101/Lander101.html                              |   41 -
 src/lessons/lander/lvl1_lander_101/Lander101.it.html                           |   45 -
 src/lessons/lander/lvl1_lander_101/Lander101.pt_BR.html                        |   45 -
 src/lessons/lander/lvl1_lander_101/Lander101.scala                             |   17 
 src/lessons/lander/lvl1_lander_101/Lander101Entity.java                        |   14 
 src/lessons/lander/lvl1_lander_101/Lander101Entity.py                          |   13 
 src/lessons/lander/lvl1_lander_101/ScalaLander101Entity.scala                  |   17 
 src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.fr.html          |   39 -
 src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.html             |   34 -
 src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.scala            |   19 
 src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.java       |   57 --
 src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.py         |   43 -
 src/lessons/lander/lvl2_locate_landing_zone/ScalaLocateLandingZoneEntity.scala |   54 --
 src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.fr.html                    |   41 -
 src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.html                       |   33 -
 src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.pt_BR.html                 |   37 -
 src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.scala                      |   20 
 src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.java                 |   48 -
 src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.py                   |   45 -
 src/lessons/lander/lvl3_fly_the_lander/ScalaFlyTheLanderEntity.scala           |   53 --
 src/lessons/lander/short_desc.fr.html                                          |    9 
 src/lessons/lander/short_desc.html                                             |    7 
 src/lessons/lander/universe/Configurations.scala                               |   77 ---
 src/lessons/lander/universe/DelegatingLanderWorld.fr.html                      |   48 -
 src/lessons/lander/universe/DelegatingLanderWorld.html                         |   44 -
 src/lessons/lander/universe/DelegatingLanderWorld.java                         |   71 --
 src/lessons/lander/universe/DelegatingLanderWorld.pt_BR.html                   |   43 -
 src/lessons/lander/universe/Geometry.scala                                     |   47 -
 src/lessons/lander/universe/LanderEntity.scala                                 |   59 --
 src/lessons/lander/universe/LanderWorld.scala                                  |  148 -----
 src/lessons/lander/universe/LanderWorldView.scala                              |  207 --------
 src/plm/core/lang/JVMCompiledLang.java                                         |    9 
 src/plm/core/lang/LangScala.java                                               |  247 ----------
 src/plm/core/model/Game.java                                                   |   51 --
 src/plm/core/model/lesson/ExerciseTemplated.java                               |    4 
 src/plm/core/model/lesson/ExerciseTemplatingEntity.java                        |   19 
 src/plm/core/ui/ChooseLessonDialog.java                                        |    2 
 src/plm/core/ui/JavaEditorPanel.java                                           |    2 
 src/plm/core/ui/editor/MissionEditor.java                                      |    6 
 src/plm/test/ExoTest.java                                                      |   13 
 src/plm/test/LessonTest.java                                                   |   10 
 src/plm/test/simple/test/AllSimpleExerciseTests.java                           |    2 
 src/plm/test/simple/test/ScalaSimpleExerciseTest.java                          |   52 --
 src/plm/universe/bat/BatExercise.java                                          |    2 
 src/plm/universe/bat/BatTest.java                                              |   16 
 50 files changed, 17 insertions(+), 2104 deletions(-)

Index: b/src/lessons/lander/universe/Configurations.scala
===================================================================
--- a/src/lessons/lander/universe/Configurations.scala
+++ /dev/null
@@ -1,77 +0,0 @@
-package lessons.lander.universe
-
-import plm.universe.World
-
-object Configurations {
-  import NumUtil._
-
-  // helper creation functions
-
-  private case class Terrain(width: Int, height: Int, ground: List[Point])
-
-  private def makeWorld(name: String, terrain: Terrain, position: Point, speed: Point,
-      angle: Double, thrust: Int, fuel: Int) =
-    new DelegatingLanderWorld(name, terrain.width, terrain.height, terrain.ground, position, speed,
-        angle, thrust, fuel)
-
-  // helper geometric functions
-
-  private def angleToSpeed(angle: Double, speed: Double) =
-    radianToVector(gameAngleToRadian(angle)) * speed
-
-  // terrains
-
-  private val SIMPLE_TERRAIN = Terrain(
-      width = 2000,
-      height = 1000,
-      ground = List(Point(0, 100), Point(125, 414), Point(205, 271),
-          Point(348, 597), Point(460, 257), Point(534, 438), Point(637, 160),
-          Point(760, 371), Point(854, 200), Point(1468, 200), Point(1585, 440),
-          Point(1682, 280), Point(1845, 668), Point(2000, 294)))
-
-  private val CHALLENGING_TERRAIN = Terrain(
-      width = 2000,
-      height = 1000,
-      ground =  List(Point(0,260), Point(37,160), Point(160,371), Point(254,200),
-          Point(430,200), Point(535,394), Point(639,300), Point(780,300), Point(890,440),
-          Point(1082,280), Point(1245,668), Point(1400,294), Point(1580, 410), Point(1730, 360),
-          Point(1870, 560), Point(2000, 400)))
-
-  // worlds
-
-  val SIMPLE_TERRAIN_TRIVIAL_CONFIG = makeWorld(
-      name = "Simple Terrain, Simple Configuration",
-      terrain = SIMPLE_TERRAIN,
-      position = Point(1200, 700),
-      speed = Point(0, 0),
-      angle = 0.0,
-      thrust = 0,
-      fuel = 3000)
-
-  val CHALLENGING_TERRAIN_SIMPLE_CONFIG = makeWorld(
-      name = "Challenging Terrain, Simple Configuration",
-      terrain = CHALLENGING_TERRAIN,
-      position = Point(530, 600),
-      speed = Point(0, 10),
-      angle = 0,
-      thrust = 4,
-      fuel = 3000)
-
-  val SIMPLE_TERRAIN_CHALLENGING_CONFIG = makeWorld(
-      name = "Simple Terrain, Challenging Configuration",
-      terrain = SIMPLE_TERRAIN,
-      position = Point(500, 500),
-      speed = angleToSpeed(-20, 20),
-      angle = -20,
-      thrust = 3,
-      fuel = 3000)
-
-  val SIMPLE_TERRAIN_HARD_CONFIG = makeWorld(
-      name = "Simple Terrain, Hard Configuration",
-      terrain = SIMPLE_TERRAIN,
-      position = Point(1900, 900),
-      speed = angleToSpeed(90, 80),
-      angle = 90,
-      thrust = 4,
-      fuel = 3000)
-}
\ No newline at end of file
Index: b/src/lessons/lander/universe/Geometry.scala
===================================================================
--- a/src/lessons/lander/universe/Geometry.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package lessons.lander.universe
-
-import Math.PI
-import Math.cos
-import Math.sin
-
-object NumUtil {
-  def clamp(min: Double, max: Double, value: Double): Double = {
-    if (value < min) min else if (value > max) max else value
-  }
-  def clamp(min: Int, max: Int, value: Int): Int = {
-    if (value < min) min else if (value > max) max else value
-  }
-
-  def radianToVector(angle: Double) = Point(cos(angle), sin(angle))
-  
-  def gameAngleToRadian(angle: Double) = (angle + 90) * PI / 180
-}
-
-case class Point(x: Double, y: Double) {
-  def +(p: Point): Point = new Point(x + p.x, y + p.y)
-  def -(p: Point): Point = new Point(x - p.x, y - p.y)
-  def *(l: Double): Point = new Point(x * l, y * l)
-  def /(l: Double): Point = new Point(x / l, y / l)
-  def unary_- = this * -1
-
-  def length: Double = Math.sqrt(x * x + y * y)
-  def normed = this / length
-  def dot(p: Point) = x * p.x + y * p.y
-  def cross(p: Point) = x * p.y - y * p.x
-}
-
-case class Segment(start: Point, end: Point)
-
-case class Ray(origin: Point, direction: Point) {
-  def intersects(s: Segment): Boolean = {
-    val v = s.end - s.start
-    val cross = direction.cross(v);
-    if (cross == 0) {
-      false
-    } else {
-      val f1 = (s.start - origin).cross(v) / cross
-      val f2 = (s.start - origin).cross(direction) / cross
-      f1 >= 0 && f2 >= 0 && f2 <= 1
-    }
-  }
-}
Index: b/src/lessons/lander/universe/LanderEntity.scala
===================================================================
--- a/src/lessons/lander/universe/LanderEntity.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package lessons.lander.universe
-
-import plm.universe.Entity
-import scala.collection.JavaConversions._
-
-class LanderEntity extends Entity {
-
-  private def landerWorld = getWorld().asInstanceOf[DelegatingLanderWorld].realWorld
-
-  override def command(command: String, out: java.io.BufferedWriter){
-    
-  }
-  
-  override def run() = {
-    initialize()
-    while (isFlying()) {
-      step()
-      simulateStep()
-    }
-  }
-
-  // methods to be overridden by the player
-  def initialize(): Unit = ()
-  def step(): Unit = ()
-
-  // query terrain2
-  def getGround(): java.util.List[Point] = landerWorld.ground
-
-  // query lander state
-  def getX(): Double = landerWorld.position.x
-  def getY(): Double = landerWorld.position.y
-  def getSpeedX(): Double = landerWorld.speed.x
-  def getSpeedY(): Double = landerWorld.speed.y
-  def getAngle(): Double = landerWorld.angle
-  def getThrust(): Int = landerWorld.thrust
-  def getFuel(): Int = landerWorld.fuel
-
-  def setDesiredAngle(desiredAngle: Double) {
-    landerWorld.desiredAngle = desiredAngle
-  }
-  def setDesiredThrust(desiredThrust: Int) {
-    landerWorld.desiredThrust = desiredThrust
-  }
-  
-  /* Internal commands used by the python entities to simulate the above run method */
-  def isFlying(): Boolean = (landerWorld.state == LanderWorld.State.FLYING)
-  def simulateStep() = {
-    landerWorld.simulate(0.1)
-    stepUI()
-  }
-  
-  /* BINDINGS TRANSLATION: French */
-  def getSol() = getGround()
-  def getVitesseX(): Double = getSpeedX()
-  def getVitesseY(): Double = getSpeedY()
-  def getPoussee(): Int = getThrust()
-  def setAngleDesire(desiredAngle: Double) = setDesiredAngle(desiredAngle) 
-  def setPousseeDesiree(desiredThrust: Int) = setDesiredThrust(desiredThrust)
-}
Index: b/src/lessons/lander/universe/LanderWorld.scala
===================================================================
--- a/src/lessons/lander/universe/LanderWorld.scala
+++ /dev/null
@@ -1,148 +0,0 @@
-package lessons.lander.universe
-
-import Math.PI
-
-import javax.script.ScriptEngine
-import javax.swing.ImageIcon
-import plm.core.lang.ProgrammingLanguage
-import plm.core.model.Game
-import plm.core.lang.ProgrammingLanguage
-import plm.core.ui.ResourcesCache
-import plm.universe.World
-
-object LanderWorld {
-  object State extends Enumeration {
-    val FLYING, LANDED, CRASHED, OUT = Value
-  }
-
-  private val GRAVITY = Point(0, -1) * 3.711;
-}
-
-class LanderWorld(val parent: DelegatingLanderWorld) {
-
-  import LanderWorld.State._
-  import NumUtil._
-
-  var width: Int = 0
-  var height: Int = 0
-  var ground: List[Point] = null
-  var position: Point = null
-  var speed: Point = null
-  /** Angle in degrees, 0 points north, 90 points west. */
-  var angle: Double = 0
-  var thrust: Int = 0
-  var fuel: Int = 0
-  var state = FLYING
-
-  var desiredAngle: Double = 0
-  var desiredThrust: Int = 0
-
-  parent.setDelay(10)
-  parent.addEntity(new LanderEntity())
-
-  // "inherited" methods
-
-  def getIcon = ResourcesCache.getIcon("img/world_lander.png");
-
-  def setupBindings(lang: ProgrammingLanguage, engine: ScriptEngine) {
-  		if (lang.equals(Game.PYTHON)) {
-  			engine.put("Segment", Segment.getClass())
-			engine.eval(
-			    "def isFlying():\n"+
-			    "  return entity.isFlying()\n"+
-			    "def simulateStep():\n"+
-			    "  entity.simulateStep()\n"+
-			    "def getGround():\n"+
-			    "  return [ (elm.x(), elm.y()) for elm in entity.getGround() ]\n"+
-			    "def getX():\n"+
-			    "  return entity.getX()\n"+
-			    "def getY():\n"+
-			    "  return entity.getY()\n"+
-			    "def getSpeedX():\n"+
-			    "  return entity.getSpeedX()\n"+
-			    "def getSpeedY():\n"+
-			    "  return entity.getSpeedY()\n"+
-			    "def getAngle():\n"+
-			    "  return entity.getAngle()\n"+
-			    "def setDesiredAngle(a):\n"+
-			    "  entity.setDesiredAngle(a)\n"+
-			    "def getThrust():\n"+
-			    "  return entity.getThrust()\n"+
-			    "def setDesiredThrust(t):\n"+
-			    "  entity.setDesiredThrust(t)\n"+
-			    "def getFuel():\n"+
-			    "  return entity.getFuel()\n"+
-			    "")
-  		} else {
-  			throw new RuntimeException("No binding of LanderWorld for "+lang)
-  		}
-  }
-
-  /** Returns true if both worlds have same name and same state. */
-  def winning(target: World): Boolean = state == LANDED
-
-  def diffTo(world: World): String = null
-
-  def reset(initialWorld: LanderWorld): Unit = {
-    width = initialWorld.width
-    height = initialWorld.height
-    ground = initialWorld.ground
-    position = initialWorld.position
-    speed = initialWorld.speed
-    angle = initialWorld.angle
-    thrust = initialWorld.thrust
-    fuel = initialWorld.fuel
-    state = initialWorld.state
-    desiredAngle = angle
-    desiredThrust = thrust
-  }
-
-  def getView() = new LanderWorldView(parent)
-
-  override def toString() = "scala lander world"
-
-  // simulation
-
-  def angleRadian = gameAngleToRadian(angle)
-
-  private def groundSegments = {
-    if (ground.isEmpty) List()
-    else (ground, ground.tail).zipped map (Segment(_, _))
-  }
-
-  private def flatSegments = groundSegments.filter((s) => s.start.y == s.end.y)
-
-  private def touchesSomeFlatSegment(p: Point) = flatSegments
-      .find((s) => p.x > s.start.x && p.x < s.end.x && p.y - s.start.y < 1)
-      .isDefined
-
-  private def isUnderground(p: Point) =
-    groundSegments.filter(new Ray(p, Point(0, 1)).intersects(_)).length % 2 == 1
-
-  def simulate(dt: Double) {
-    if (state == FLYING) {
-      angle = clamp(-90.0 max (angle - 5), 90.0 min (angle + 5), desiredAngle)
-      thrust = clamp(0 max (thrust - 1), 5 min (thrust + 1), desiredThrust) min fuel
-      val force = radianToVector(angleRadian) * thrust + LanderWorld.GRAVITY
-      position = position + speed * dt
-      speed = speed + force * dt
-      fuel = (fuel - thrust) max 0
-
-      lazy val underground = isUnderground(position)
-      lazy val goodConfig = speed.y.abs <= 10 && speed.x.abs <= 5 && (angleRadian - PI/2) < 1e-2
-      lazy val touchesFlat = touchesSomeFlatSegment(position)
-      lazy val outOfWorldX = position.x < 0 || position.x > width
-      lazy val outOfWorldY = position.y < 0 || position.y > height
-      lazy val outOfWorld = outOfWorldX || outOfWorldY
-
-      state =
-        if (underground) {
-          if (goodConfig && touchesFlat) LANDED
-          else CRASHED
-        } else {
-          if (outOfWorld) OUT
-          else FLYING
-        }
-    }
-  }
-}
Index: b/src/lessons/lander/universe/LanderWorldView.scala
===================================================================
--- a/src/lessons/lander/universe/LanderWorldView.scala
+++ /dev/null
@@ -1,207 +0,0 @@
-package lessons.lander.universe
-
-import plm.core.ui.WorldView
-import plm.universe.World
-import java.awt.Graphics
-import java.awt.Graphics2D
-import java.awt.RenderingHints
-import java.awt.Color
-import java.awt.geom.Rectangle2D
-import java.awt.geom.Line2D
-import java.awt.BasicStroke
-import java.awt.geom.AffineTransform
-import java.awt.geom.GeneralPath
-import java.awt.geom.Path2D
-import Math.PI
-import java.awt.geom.QuadCurve2D
-import scala.util.Random
-import java.awt.Font
-import java.awt.event.MouseListener
-import java.awt.event.MouseMotionListener
-import java.awt.event.MouseMotionAdapter
-import java.awt.event.MouseEvent
-import java.awt.event.MouseAdapter
-import java.awt.geom.Point2D
-
-object LanderWorldView {
-  private val LANDER_SHAPE = List(
-      List(Point(-2, 3), Point(-3, 4), Point(-3, 7), Point(-2, 8), Point(2, 8), Point(3, 7),
-          Point(3, 4), Point(2, 3), Point(-2, 3)),
-      List(Point(-6, 0), Point(-4, 0)),
-      List(Point(6, 0), Point(4, 0)),
-      List(Point(-5, 0), Point(-4, 2.8), Point(-2, 3)),
-      List(Point(5, 0), Point(4, 2.8), Point(2, 3)))
-
-  private val EXPLOSION_SHAPE = List(
-      Point(-4, 3), Point(-1, 2), Point(0, 4), Point(1, 2), Point(4, 2), Point(2, 0),
-      Point(3, -2), Point(0, -1), Point(-3, -3), Point(-2, 0), Point(-4, 3))
-}
-
-class LanderWorldView(delagatingWorld: DelegatingLanderWorld) extends WorldView(delagatingWorld) {
-
-  import LanderWorld.State._
-
-  private def realWorld = world.asInstanceOf[DelegatingLanderWorld].realWorld
-
-  private var mouseIn : Boolean = false
-  private var mousePos : Point = Point(0, 0)
-
-  addMouseListener(new MouseAdapter() {
-    override def mouseEntered(e: MouseEvent) {
-      mouseIn = true
-    }
-    override def mouseExited(e: MouseEvent) {
-      mouseIn = false
-      repaint()
-    }
-  })
-
-  addMouseMotionListener(new MouseMotionAdapter() {
-    override def mouseMoved(event: MouseEvent) = {
-      mousePos = Point(event.getX, event.getY)
-      repaint()
-    }
-  })
-
-  override def paintComponent(g: Graphics) = {
-    super.paintComponent(g);
-    val g2 = g.asInstanceOf[Graphics2D];
-    new Painter(g2).paint()
-  }
-
-  private class Painter(g2: Graphics2D) {
-    def paint() {
-      val initialTransform = g2.getTransform()
-      setupRendering()
-      clearWidgetBackground()
-      setupGlobalTransform()
-      clearWorldBackground()
-      drawGround()
-      drawStats(initialTransform)
-      realWorld.state match {
-        case FLYING => drawLander(drawFlame = true)
-        case LANDED => drawLander(drawFlame = false)
-        case OUT => drawQuestionMarks()
-        case CRASHED => drawExplosion()
-      }
-    }
-
-    def setupRendering() {
-      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
-    }
-
-    def clearWidgetBackground() = {
-      g2.setColor(Color.gray)
-      g2.fill(new Rectangle2D.Double(0, 0, getWidth, getHeight))
-    }
-
-    def setupGlobalTransform() = {
-      val scale = (getWidth.toDouble / realWorld.width) min (getHeight.toDouble / realWorld.height)
-      val translateX = (getWidth - realWorld.width * scale) / 2
-      val translateY = (getHeight + realWorld.height * scale) / 2
-      g2.translate(translateX, translateY)
-      g2.scale(scale, -scale)
-    }
-
-    def clearWorldBackground() = {
-      g2.setColor(Color.black);
-      g2.fill(new Rectangle2D.Double(0, 0, realWorld.width, realWorld.height));
-    }
-
-    /** Sets the line width to 1px no matter the transform, and the color to white. */
-    def resetPen() {
-      val transform = g2.getTransform();
-      val scale = (transform.getScaleX() min transform.getScaleY()).abs;
-      g2.setStroke(new BasicStroke((1 / scale).toFloat))
-      g2.setColor(Color.white)
-    }
-
-    def drawPath(path: List[Point], fill: Boolean) {
-      if (!path.isEmpty) {
-        val polyLine = new GeneralPath(Path2D.WIND_EVEN_ODD, path.length)
-        polyLine.moveTo(path.head.x, path.head.y)
-        for (point <- path.tail) {
-          polyLine.lineTo(point.x, point.y)
-        }
-        if (fill) {
-          g2.fill(polyLine)
-        } else {
-          g2.draw(polyLine)
-        }
-      }
-    }
-
-    def drawText(text: String, x: Double, y: Double) {
-      val oldTransform = g2.getTransform()
-      g2.translate(x, y)
-      g2.scale(1, -1)
-      g2.drawString(text, 0, 0)
-      g2.setTransform(oldTransform)
-    }
-
-    def drawGround() = {
-      resetPen()
-      drawPath(realWorld.ground, fill = false)
-    }
-
-    def randomScaleFactor() = 1 + Random.nextDouble() * 0.2
-
-    def drawLander(drawFlame: Boolean) = {
-      val oldTransform = g2.getTransform()
-      g2.translate(realWorld.position.x, realWorld.position.y)
-      g2.scale(6, 6)  // the lander shape is small
-      resetPen()
-      g2.rotate(realWorld.angleRadian - PI/2)
-      LanderWorldView.LANDER_SHAPE.foreach(drawPath(_, fill = false))
-      val thrust = realWorld.thrust
-      if (drawFlame && thrust > 0) {
-        val controlX = (0.4 + thrust * 0.1) * randomScaleFactor()
-        val endY = (-2 * thrust) * randomScaleFactor()
-        val controlY = (endY + 3) / 2
-        g2.draw(new QuadCurve2D.Double(-0.25, 3, -controlX, controlY, 0, endY))
-        g2.draw(new QuadCurve2D.Double(0.25, 3, controlX, controlY, 0, endY))
-      }
-      g2.setTransform(oldTransform)
-    }
-
-    def drawExplosion() = {
-      val oldTransform = g2.getTransform()
-      g2.translate(realWorld.position.x, realWorld.position.y)
-      g2.scale(15, 15)  // the explosion shape is small
-      resetPen()
-      drawPath(LanderWorldView.EXPLOSION_SHAPE, fill = true)
-      g2.setTransform(oldTransform)
-    }
-
-    def drawQuestionMarks() = {
-      val x = realWorld.position.x
-      val y = realWorld.position.y
-      val textX = if (x >= realWorld.width) realWorld.width - 100 else if (x <= 0) 5 else x
-      val textY = if (y >= realWorld.height) realWorld.height - 40 else if (y <= 0) 5 else y - 30
-      g2.setColor(Color.WHITE)
-      g2.setFont(new Font(Font.MONOSPACED, Font.BOLD, 40))
-      drawText("???", textX, textY)
-    }
-
-    def drawStats(initialTransform: AffineTransform) {
-      g2.setColor(Color.LIGHT_GRAY)
-      g2.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 30))
-      drawText(f"x: ${realWorld.position.x}%.2f", 5, realWorld.height - 30)
-      drawText(f"y: ${realWorld.position.y}%.2f", 5, realWorld.height - 2 * 30)
-      drawText(f"speed x: ${realWorld.speed.x}%.2f", 5, realWorld.height - 3 * 30)
-      drawText(f"speed y: ${realWorld.speed.y}%.2f", 5, realWorld.height - 4 * 30)
-      drawText(f"angle: ${realWorld.angle}%.2f°", 5, realWorld.height - 5 * 30)
-      drawText(f"thrust: ${realWorld.thrust}", 5, realWorld.height - 6 * 30)
-      drawText(f"fuel: ${realWorld.fuel}", 5, realWorld.height - 7 * 30)
-
-      if (mouseIn) {
-        val deltaTransform = new AffineTransform(g2.getTransform())
-        deltaTransform.invert()
-        deltaTransform.concatenate(initialTransform)
-        val coord = deltaTransform.transform(new Point2D.Double(mousePos.x, mousePos.y), null)
-        drawText(f"x: ${coord.getX.round}", realWorld.width - 130, realWorld.height - 30)
-        drawText(f"y: ${coord.getY.round}", realWorld.width - 130, realWorld.height - 2 * 30)
-      }
-    }
-  }
-}
Index: b/src/lessons/lander/Main.fr.html
===================================================================
--- a/src/lessons/lander/Main.fr.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Alunisseur</h1>
-
-<p>Dans cette leçon, vous pilotez un alunisseur dans des situations de plus en
-plus complexes.</p>
-
-<p>À chaque pas de la simulation, le joueur donne des commandes contrôlant
-l'angle et la poussée du module d'alunissage.</p>
-
-<p>Idées d'exercices à ajouter à la progression proposée :</p>
-<ul>
-  <li>Un alunisseur en position verticale au dessus d'un sol plat. Le joueur ne
-peut régler que la poussée (c'est fait).</li>
-  <li>Un alunisseur en position verticale pas au dessus d'un sol plat. Le joueur
-peut régler la poussée et l'angle (c'est fait).</li>
-  <li>Un alunisseur avec un angle et une vitesse difficile, pas au dessus d'un sol
-plat. Le joueur contrôle la poussée et l'angle.</li>
-  <li>Un alunisseur avec un angle et une vitesse difficile, pas au dessus d'un sol
-plat dans une configuration difficile. Le joueur contrôle la poussée et
-l'angle.</li>
-  <li>La même chose avec du vent ?</li>
-</ul>
Index: b/src/lessons/lander/Main.html
===================================================================
--- a/src/lessons/lander/Main.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Lunar Lander</h1>
-
-<p>In this lesson you pilot a lunar landing module in increasingly complex
-situations.</p>
-
-<p>At each step of the simulation, the player issues a command controlling how
-much the angle and thrust of the lander should change</p>
-
-<p>Ideas concerning the progression of exercises:</p>
-<ul>
-  <li>A lander in vertical position above flat ground, the player can only
-control thrust (done)</li>
-  <li>A lander in vertical position not above flat ground, the player control
-thrust and angle (done)</li>
-  <li>A lander with difficult angle and speed not above flat ground, the
-player control thrust and angle</li>
-  <li>A lander with difficult angle and speed not above flat ground, with
-difficult ground, the player control thrust and angle</li>
-  <li>Same with wind?</li>
-</ul>
Index: b/src/lessons/lander/Main.scala
===================================================================
--- a/src/lessons/lander/Main.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package lessons.lander
-
-import plm.core.model.lesson.Lesson
-import lessons.lander.lvl1_lander_101.Lander101
-import lessons.lander.lvl2_locate_landing_zone.LocateLandingZone
-import lessons.lander.lvl3_fly_the_lander.FlyTheLander
-
-class Main extends Lesson {
-  override def loadExercises = {
-    addExercise(new Lander101(this));
-    addExercise(new LocateLandingZone(this));
-    addExercise(new FlyTheLander(this));
-  }
-}
Index: b/src/lessons/lander/icon.svg
===================================================================
--- a/src/lessons/lander/icon.svg
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="64"
-   height="64"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="lander.svg"
-   inkscape:export-filename="/home/polux/projects/PLM/src/lessons/lander/lander.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90">
-  <defs
-     id="defs4" />
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="7.9195959"
-     inkscape:cx="29.558295"
-     inkscape:cy="29.181329"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:window-width="1600"
-     inkscape:window-height="883"
-     inkscape:window-x="0"
-     inkscape:window-y="17"
-     inkscape:window-maximized="0">
-    <inkscape:grid
-       type="xygrid"
-       id="grid2985"
-       empspacing="5"
-       visible="true"
-       enabled="true"
-       snapvisiblegridlinesonly="true" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(0,-988.36215)">
-    <g
-       id="g3008"
-       transform="translate(2,8)">
-      <path
-         sodipodi:nodetypes="ccccccccc"
-         transform="translate(0,988.36215)"
-         inkscape:connector-curvature="0"
-         id="path2987"
-         d="m 20,4 20,0 5,5 0,15 -5,5 -20,0 -5,-5 0,-15 z"
-         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-      <path
-         sodipodi:nodetypes="ccc"
-         transform="translate(0,988.36215)"
-         inkscape:connector-curvature="0"
-         id="path2989"
-         d="M 20,29 10,30 5,44"
-         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-      <path
-         sodipodi:nodetypes="ccc"
-         transform="translate(0,988.36215)"
-         inkscape:connector-curvature="0"
-         id="path2993"
-         d="m 40,29 10,1 5,14"
-         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-      <path
-         transform="translate(0,988.36215)"
-         inkscape:connector-curvature="0"
-         id="path3004"
-         d="m 0,44 10,0"
-         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-      <path
-         transform="translate(0,988.36215)"
-         inkscape:connector-curvature="0"
-         id="path3006"
-         d="m 50,44 10,0"
-         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-    </g>
-  </g>
-</svg>
Index: b/src/lessons/lander/lvl1_lander_101/Lander101.fr.html
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/Lander101.fr.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Se poser pour les nuls</h1>
-
-<p>Bravo ! Vous avez gagné dans une boîte de céréales un voyage (aller simple)
-pour Mars. La NASA vous a même fourni un module d'excursion lunaire pour
-l'occasion, et c'est donc avec ce véhicule que vous voyagerez.</p>
-
-<p>Avant le décollage, vous devez vous entraîner sur simulateur aux bases de
-l'alunissage. Si tout se passe comme prévu, vous ne devriez pas avoir à
-voler en mode manuel, mais mieux vaut prévenir que guérir, comme ils disent.</p>
-
-<p>Votre mission est de <b>poser le module avec une vitesse verticale
-inférieure à 10 m/s</b>. Il y a deux façons d'influer sur la trajectoire du
-module : en modifiant son angle, ou en réglant la poussée de son
-moteur. Dans cette simulation, nous ne nous intéressons qu'à la poussée,
-exprimée en m/s².</p>
-
-<p>Vous devez écrire le [!python]corps de la fonction <code>step()</code>, qui
-sera appelée[/!][!scala|java|c]code qui sera appellé[/!] tous les dixièmes
-de seconde pendant la simulation. Il faut ajuster la poussée du moteur en
-utilisant la fonction <code>[!java]void [/!]setPousseeDesiree([!java]int
-[/!]poussee[!scala]:Integer[/!])</code> où <code>poussee</code> est un
-entier entre 0 et 4 (représentant une poussée entre 0 m/s² et 4 m/s²). Vous
-ne pouvez incrémenter ou décrémenter la poussée que de 1 entre deux pas de
-la simulation. Ainsi, si la poussée du moteur est actuellement de 2 et que
-vous demandez 4, vous n'aurez que 3 à la prochaine étape. Si vous demandez
-une valeur inférieure à 0 (ou supérieure à 4), tout se passera comme si vous
-aviez demandé 0 (ou 4).</p>
-
-<p>Afin de prendre des décisions informées, vous pouvez demander des
-informations sur l'état actuel du module. Dans cette simulation, vous ne
-serez probablement intéressé que par sa position verticale (accessible grâce
-à <code>[!java]double [/!]getY()[!scala]:Double[/!]</code>) et sa vitesse
-verticale (accessible grâce à <code>[!java]double
-[/!]getVitesseY()[!scala]:Double[/!]</code>). Vous pouvez également demander
-la poussée actuelle du moteur (avec <code>[!java]int
-[/!]getPoussee()[!scala]:Integer[/!]</code>) si vous avez oublié ce que vous
-avez demandé. Rappelez vous que la gravité martienne est de 3.711 m/s², cela
-peut vous être utile.</p>
-
-<p>Une dernière chose : le module est plutôt petit, et vous n'avez pas tant de
-carburant que cela. À chaque pas de simulation, il consomme autant d'unité
-de carburant que la poussée actuelle du moteur. Si vous tombez en panne
-sèche, vous serez en chute libre alors attention ! Vous pouvez consulter le
-niveau du réservoir avec <code>[!java]int
-[/!]getFuel()[!scala]:Integer[/!]</code>.</p>
-
-<p>Bon courage !</p>
Index: b/src/lessons/lander/lvl1_lander_101/Lander101.html
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/Lander101.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Lander 101</h1>
-
-<p>Congratulations! You won a (one-way) trip to Mars in a cereal box. NASA was
-kind enough to donate the Lunar Excursion Module for this mission, so
-that's what you'll be flying.</p>
-
-<p>Before you take off, you must go through some basic landing simulation. You
-shouldn't have to fly the lander if all goes as planned but, as they say,
-"better safe than sorry".</p>
-
-<p>Your mission is to <b>land the lander with a vertical speed of at most 10
-m/s.</b> There are two ways you can influence the lander's course: by adjusting
-its angle or by adjusting its thrust. In this simulation we only care about
-adjusting the thrust, expressed in m/s².</p>
-
-<p>The [!python]<code>step()</code> function[/!][!scala|java|c]code[/!] that you 
-should write now will be called every 0.1 second during the simulation. It should 
-set the desired thrust of the next simulation step, by calling 
-<code>[!java]void [/!]setDesiredThrust([!java]int [/!]desiredThrust[!scala]:Integer[/!])</code> 
-where <code>desiredThrust</code> is some integer between 0 and 4 (that is, a thrust 
-between 0 m/s² and 4 m/s²). You can only increment or decrement the thrust by 1 
-between two simulation steps, so if the current thrust is 2 and you ask for 4, 
-you'll only get 3 in the next step. If you ask for less than 0 (resp. more than 4), 
-everything will be as if you had asked for 0 (resp. 4).</p>
-
-<p>In order to take informed decisions, you can query the lander's state. In
-this simulation you'll probably be interested in its vertical position:
-<code>[!java]double [/!]getY()[!scala]:Double[/!]</code>, and its vertical speed: 
-<code>[!java]double [/!]getSpeedY()[!scala]:Double[/!]</code>. You can also ask for 
-the thrust via <code>[!java]int [/!]getThrust()[!scala]:Integer[/!]</code> in case 
-you don't remember what you asked for. Remember that Mars' gravity is 3.711 m/s², 
-it might come in handy.</p>
-
-<p>One last thing: the lander is pretty small so you don't have much fuel. At
-each step of the simulation the lander consumes as many fuel units as the
-current thrust. Once you run out of fuel you're in free fall so beware! You can
-consult the remaining amount of available fuel units using 
-<code>[!java]int [/!]getFuel()[!scala]:Integer[/!]</code>.</p>
-
-<p>Good luck!</p>
Index: b/src/lessons/lander/lvl1_lander_101/Lander101.it.html
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/Lander101.it.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Lander 101</h1>
-
-<p>Congratulations! You won a (one-way) trip to Mars in a cereal box. NASA was
-kind enough to donate the Lunar Excursion Module for this mission, so that's
-what you'll be flying.</p>
-
-<p>Before you take off, you must go through some basic landing simulation. You
-shouldn't have to fly the lander if all goes as planned but, as they say,
-"better safe than sorry".</p>
-
-<p>Your mission is to <b>land the lander with a vertical speed of at most 10
-m/s.</b> There are two ways you can influence the lander's course: by
-adjusting its angle or by adjusting its thrust. In this simulation we only
-care about adjusting the thrust, expressed in m/s².</p>
-
-<p>The [!python]<code>step()</code> function[/!][!scala|java|c]code[/!] that
-you should write now will be called every 0.1 second during the
-simulation. It should set the desired thrust of the next simulation step, by
-calling <code>[!java]void [/!]setDesiredThrust([!java]int
-[/!]desiredThrust[!scala]:Integer[/!])</code> where
-<code>desiredThrust</code> is some integer between 0 and 4 (that is, a
-thrust between 0 m/s² and 4 m/s²). You can only increment or decrement the
-thrust by 1 between two simulation steps, so if the current thrust is 2 and
-you ask for 4, you'll only get 3 in the next step. If you ask for less than
-0 (resp. more than 4), everything will be as if you had asked for 0
-(resp. 4).</p>
-
-<p>In order to take informed decisions, you can query the lander's state. In
-this simulation you'll probably be interested in its vertical position:
-<code>[!java]double [/!]getY()[!scala]:Double[/!]</code>, and its vertical
-speed: <code>[!java]double [/!]getSpeedY()[!scala]:Double[/!]</code>. You
-can also ask for the thrust via <code>[!java]int
-[/!]getThrust()[!scala]:Integer[/!]</code> in case you don't remember what
-you asked for. Remember that Mars' gravity is 3.711 m/s², it might come in
-handy.</p>
-
-<p>One last thing: the lander is pretty small so you don't have much fuel. At
-each step of the simulation the lander consumes as many fuel units as the
-current thrust. Once you run out of fuel you're in free fall so beware! You
-can consult the remaining amount of available fuel units using
-<code>[!java]int [/!]getFuel()[!scala]:Integer[/!]</code>.</p>
-
-<p>Buona fortuna!</p>
Index: b/src/lessons/lander/lvl1_lander_101/Lander101.pt_BR.html
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/Lander101.pt_BR.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Lander 101</h1>
-
-<p>Congratulations! You won a (one-way) trip to Mars in a cereal box. NASA was
-kind enough to donate the Lunar Excursion Module for this mission, so that's
-what you'll be flying.</p>
-
-<p>Before you take off, you must go through some basic landing simulation. You
-shouldn't have to fly the lander if all goes as planned but, as they say,
-"better safe than sorry".</p>
-
-<p>Your mission is to <b>land the lander with a vertical speed of at most 10
-m/s.</b> There are two ways you can influence the lander's course: by
-adjusting its angle or by adjusting its thrust. In this simulation we only
-care about adjusting the thrust, expressed in m/s².</p>
-
-<p>The [!python]<code>step()</code> function[/!][!scala|java|c]code[/!] that
-you should write now will be called every 0.1 second during the
-simulation. It should set the desired thrust of the next simulation step, by
-calling <code>[!java]void [/!]setDesiredThrust([!java]int
-[/!]desiredThrust[!scala]:Integer[/!])</code> where
-<code>desiredThrust</code> is some integer between 0 and 4 (that is, a
-thrust between 0 m/s² and 4 m/s²). You can only increment or decrement the
-thrust by 1 between two simulation steps, so if the current thrust is 2 and
-you ask for 4, you'll only get 3 in the next step. If you ask for less than
-0 (resp. more than 4), everything will be as if you had asked for 0
-(resp. 4).</p>
-
-<p>In order to take informed decisions, you can query the lander's state. In
-this simulation you'll probably be interested in its vertical position:
-<code>[!java]double [/!]getY()[!scala]:Double[/!]</code>, and its vertical
-speed: <code>[!java]double [/!]getSpeedY()[!scala]:Double[/!]</code>. You
-can also ask for the thrust via <code>[!java]int
-[/!]getThrust()[!scala]:Integer[/!]</code> in case you don't remember what
-you asked for. Remember that Mars' gravity is 3.711 m/s², it might come in
-handy.</p>
-
-<p>One last thing: the lander is pretty small so you don't have much fuel. At
-each step of the simulation the lander consumes as many fuel units as the
-current thrust. Once you run out of fuel you're in free fall so beware! You
-can consult the remaining amount of available fuel units using
-<code>[!java]int [/!]getFuel()[!scala]:Integer[/!]</code>.</p>
-
-<p>Boa Sorte!</p>
Index: b/src/lessons/lander/lvl1_lander_101/Lander101.scala
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/Lander101.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package lessons.lander.lvl1_lander_101
-
-import plm.core.model.lesson.ExerciseTemplated
-import plm.core.model.lesson.Lesson
-import lessons.lander.universe.DelegatingLanderWorld
-import lessons.lander.universe.Point
-import lessons.lander.universe.LanderEntity
-import lessons.lander.universe.Configurations._
-import Math.PI
-import scala.collection.JavaConversions._
-import lessons.lander.universe.LanderWorld
-import plm.universe.World
-
-class Lander101(lesson: Lesson) extends ExerciseTemplated(lesson, null) {
-  tabName = "Lander"
-  setup(SIMPLE_TERRAIN_TRIVIAL_CONFIG)
-}
Index: b/src/lessons/lander/lvl1_lander_101/Lander101Entity.java
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/Lander101Entity.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package lessons.lander.lvl1_lander_101;
-
-import lessons.lander.universe.LanderEntity;
-
-public class Lander101Entity extends LanderEntity {
-  @Override
-  public void step() {
-    /* BEGIN TEMPLATE */
-    /* BEGIN SOLUTION */
-    setDesiredThrust(getSpeedY() < -9 ? 4 : 3);
-    /* END SOLUTION */
-    /* END TEMPLATE */
-  }
-}
Index: b/src/lessons/lander/lvl1_lander_101/Lander101Entity.py
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/Lander101Entity.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# BEGIN TEMPLATE
-def step():
-# BEGIN SOLUTION
-    if getSpeedY() < -9:
-        setDesiredThrust(4)
-    else:
-        setDesiredThrust(3)
-# END SOLUTION
-# END TEMPLATE 
-
-while isFlying():
-  step()
-  simulateStep()
Index: b/src/lessons/lander/lvl1_lander_101/ScalaLander101Entity.scala
===================================================================
--- a/src/lessons/lander/lvl1_lander_101/ScalaLander101Entity.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package lessons.lander.lvl1_lander_101;
-
-import lessons.lander.universe._;
-
-class ScalaLander101Entity extends LanderEntity {
-	override def step() {
-		/* BEGIN TEMPLATE */
-		/* BEGIN SOLUTION */
-		if (getSpeedY() < -9) {
-			setDesiredThrust(4)
-		} else {
-			setDesiredThrust(3);
-		}
-		/* END SOLUTION */
-		/* END TEMPLATE */
-	}
-}
Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.fr.html
===================================================================
--- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.fr.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h2>Repérer une zone plate</h2>
-
-<p>Après 200 jours de voyage intersidéral à manger des céréales, vous êtes
-enfin parvenu à la planète rouge. Il est enfin temps de se poser !</p>
-
-<p>Le module est en pilote automatique, et vous n'avez qu'à regarder autour de
-vous pour sélectionner une zone d'alunissage. Vous devez vous poser sur
-<b>une zone plate</b> si vous ne voulez pas vous scratcher. Vous indiquez au
-pilote automatique où se poser en modifiant la fonction
-<code>getLandingZone</code> de façon à ce qu'elle retourne [!java|scala]un
-Segment représentant la zone de votre choix.
-
-<p>Un Segment est composé de deux <code>Point</code>s, chacun composé de deux
-doubles. On construit un nouveau segment de la façon suivante :
-<code>Segment([!java]Point [/!]debut[!scala]:Point[/!], [!java]Point
-[/!]fin[!scala]:Point[/!])</code>. Pour créer de nouveaux points, il faut
-utiliser le constructeur <code>Point([!java]double [/!]x[!scala]:Double[/!],
-[!java]double [/!]y[!scala]:Double[/!])</code>. Les coordonnées d'un point
-sont accessibles grâce à ses méthodes <code>[!java]double
-[/!]x()[!scala]:Double[/!]</code> et <code>[!java]double
-[/!]y()[!scala]:Double[/!]</code>.</p>[/!] [!python]tuple de deux coordonnées X délimitant la zone de votre
-choix.[/!]
-
-<p>Pour déterminer la zone cible, vous devez appeler
-<code>[!java]List&lt;Point&gt; [/!]getSol()[!scala]:List[Point][/!]</code>,
-qui retourne les points qui composent la surface sous la forme d'une list de
-[!java|scala]<code>Point</code>[/!] [!python]tuples (x,y)[/!].</p>
-
-<p>Une dernière chose : votre fonction doit retourner une zone valide dans
-toutes les situations, pas seulement celle que l'on voit en ce moment. C'est
-que votre code sera utilisé dans ce cas, mais également dans la
-configuration que nous avions dans l'exercice précédent. Comme d'habitude,
-vous pouvez voir les autres mondes en les sélectionnant dans le combobox au
-dessus de la vue du monde.</p>
-
-<p>Bon alunissage ! N'oubliez pas de mettre votre combinaison spatiale en
-sortant.</p>
Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.html
===================================================================
--- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h2>Locate a Landing Zone</h2>
-
-<p>After 200 days of traveling space and eating cereals you finally reach
-Mars. Time to land at last!</p>
-
-<p>The lander is on autopilot and all you have to do is look around and tell it
-where to land. The lander must <b>land on a flat zone</b> it you want to remain
-in one piece. You indicate the lander where to land by modifying the
-<code>getLandingZone</code> function so that it returns a 
-[!java|scala]<code>Segment</code> representing the zone of your choice.
-
-<p>A segment is composed of two <code>Point</code>s, each of them composed of
-two <code>double</code>s. A segment is built via the 
-<code>Segment([!java]Point [/!]start[!scala]:Point[/!], [!java]Point [/!]end[!scala]:Point[/!])</code> constructor. 
-A point is built via the <code>Point([!java]double [/!]x[!scala]:Double[/!], [!java]double [/!]y[!scala]:Double[/!])</code> constructor. A point's coordinates are accessible via its
-<code>[!java]double [/!]x()[!scala]:Double[/!]</code> and
-<code>[!java]double [/!]y()[!scala]:Double[/!]</code> methods.</p>[/!]
-
-[!python]tuple of two X coordinates representing the zone of your choice.[/!]
-
-<p>In order to determine which zone to return, you'll need to call
-<code>[!java]List&lt;Point&gt; [/!]getGround()[!scala]List[Point][/!]</code>, which returns 
-the vertices of the ground's profile as a list of 
-[!java|scala]<code>Point</code>[/!] [!python]tuples (x,y)[/!].</p>
-
-<p>One more thing: your function should return a valid flat zone in any kind of
-situation, not just for the currently visualized one. That's because it will
-be not only tested against that world, but also against the one we had in the
-previous exercise. As usual, you can see the other existing worlds with the
-appropriate combobox.</p>
-
-<p>Have a safe landing! Don't forget to put on your space suit on your way
-out.</p>
Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.scala
===================================================================
--- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZone.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package lessons.lander.lvl2_locate_landing_zone
-
-import plm.core.model.lesson.ExerciseTemplated
-import plm.core.model.lesson.Lesson
-import lessons.lander.universe.DelegatingLanderWorld
-import lessons.lander.universe.Point
-import lessons.lander.universe.LanderEntity
-import lessons.lander.universe.Configurations._
-import Math.PI
-import scala.collection.JavaConversions._
-import lessons.lander.universe.LanderWorld
-import plm.universe.World
-
-class LocateLandingZone(lesson: Lesson) extends ExerciseTemplated(lesson, null) {
-  tabName = "Lander"
-  setup(Array(
-      CHALLENGING_TERRAIN_SIMPLE_CONFIG,
-      SIMPLE_TERRAIN_TRIVIAL_CONFIG))
-}
Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.java
===================================================================
--- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package lessons.lander.lvl2_locate_landing_zone;
-
-import java.util.Iterator;
-
-import lessons.lander.universe.LanderEntity;
-import lessons.lander.universe.Point;
-import lessons.lander.universe.Segment;
-
-public class LocateLandingZoneEntity extends LanderEntity {
-  /* BEGIN TEMPLATE */
-  public Segment getLandingZone() {
-    /* return new Segment(new Point(0,0), new Point(0,0)); */
-    /* BEGIN SOLUTION */
-    Iterator<Point> ground = getGround().iterator();
-    Point lastPoint = ground.next();
-    while (ground.hasNext()) {
-      Point point = ground.next();
-      if (lastPoint.y() == point.y()) {
-        return new Segment(lastPoint, point);
-      }
-      lastPoint = point;
-    }
-    return null;
-    /* END SOLUTION */
-  }
-  /* END TEMPLATE */
-
-  /* BEGIN HIDDEN */
-  double targetStart = 0;
-  double targetEnd = 0;
-
-  @Override
-  public void initialize() {
-    Segment landingZone = getLandingZone();
-    targetStart = landingZone.start().x();
-    targetEnd = landingZone.end().x();
-  }
-
-  @Override
-  public void step() {
-    if (getX() < targetStart) {
-      setDesiredAngle(-30);
-    } else if (getX() > targetEnd) {
-      setDesiredAngle(30);
-    } else {
-      if (getSpeedX() > 5) {
-        setDesiredAngle(25);
-      } else if (getSpeedX() < -5) {
-        setDesiredAngle(-25);
-      } else {
-        setDesiredAngle(0);
-      }
-    }
-    setDesiredThrust(getSpeedY() < -9 ? 4 : 3);
-  }
-  /* END HIDDEN */
-}
Index: b/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.py
===================================================================
--- a/src/lessons/lander/lvl2_locate_landing_zone/LocateLandingZoneEntity.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# BEGIN TEMPLATE
-def getLandingZone():
-    # BEGIN SOLUTION
-    lastPoint = getGround()[0]
-    for point in getGround():
-        if (point != lastPoint):
-            if lastPoint[1] == point[1]:
-                return (lastPoint[0],point[0])
-        lastPoint = point
-    # END SOLUTION
-# END TEMPLATE 
-
-targetStart = 0;
-targetEnd = 0;
-
-def initialize():
-    global targetStart
-    global targetEnd
-    (targetStart, targetEnd) = getLandingZone()
-    if (targetStart > targetEnd):
-        print ("Your starting point is after your ending point ("+str(targetStart)+">"+str(targetEnd)+"). Bad things will happen")
-
-def step():
-    if (getX() < targetStart):
-        setDesiredAngle(-30)
-    elif (getX() > targetEnd):
-        setDesiredAngle(30)
-    elif (getSpeedX() > 5):
-        setDesiredAngle(25)
-    elif (getSpeedX() < -5):
-        setDesiredAngle(-25)
-    else:
-        setDesiredAngle(0);
-        
-    if (getSpeedY() <-9):
-        setDesiredThrust(4)
-    else:
-        setDesiredThrust(3)
-
-initialize()
-while isFlying():
-  step()
-  simulateStep()
Index: b/src/lessons/lander/lvl2_locate_landing_zone/ScalaLocateLandingZoneEntity.scala
===================================================================
--- a/src/lessons/lander/lvl2_locate_landing_zone/ScalaLocateLandingZoneEntity.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package lessons.lander.lvl2_locate_landing_zone;
-
-import java.util.Iterator;
-import scala.collection.JavaConversions._
-
-import lessons.lander.universe._;
-
-class ScalaLocateLandingZoneEntity extends LanderEntity {
-  /* BEGIN TEMPLATE */
-  def getLandingZone():Segment = {
-    /* BEGIN SOLUTION */
-    var lastPoint:Point = getGround.get(0);
-    for (point <- getGround()) {
-      if (point != lastPoint) { // Avoid the loop when point is on the first element
-        if (point.y == lastPoint.y)
-          return new Segment(lastPoint,point)
-      }
-      lastPoint = point
-    }
-    return null;
-    /* END SOLUTION */
-  }
-  /* END TEMPLATE */
-
-  var targetStart = 0.0;
-  var targetEnd = 0.0;
-
-  override def initialize() {
-    var landingZone = getLandingZone();
-    targetStart = landingZone.start.x;
-    targetEnd = landingZone.end.x;
-  }
-
-  override def step() {
-    if (getX() < targetStart) {
-      setDesiredAngle(-30);
-    } else if (getX() > targetEnd) {
-      setDesiredAngle(30);
-    } else {
-      if (getSpeedX() > 5) {
-        setDesiredAngle(25);
-      } else if (getSpeedX() < -5) {
-        setDesiredAngle(-25);
-      } else {
-        setDesiredAngle(0);
-      }
-    }
-    
-    if (getSpeedY() < -9)
-      setDesiredThrust(4)
-    else
-      setDesiredThrust(3)
-  }
-}
Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.fr.html
===================================================================
--- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.fr.html
+++ /dev/null
@@ -1,41 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Aux commandes du module</h1>
-
-<p>Après 30 jours à regarder des cailloux en mangeant des céréales, vous
-décidez qu'il est temps d'aller explorer d'autres coins de cette planète.</p>
-
-<p>Vous volez un moment, avant de réaliser soudain que vous êtes presque à
-court d'essence. Le pilote automatique est malheureusement inutile dans ce
-genre de situation périlleuse, et vous allez devoir vous poser en mode
-manuel. Votre mission et de vous <b>poser sur une zone plate, avec une
-vitesse verticale inférieure à 10 m/s, une vitesse horizontale inférieure à
-5 m/s et un angle de 0°</b>.</p>
-
-<p>Vous devez définir deux fonctions : <code>[!java]void
-[/!]initialize()</code> et <code>[!java]void
-[/!]step()</code>. <code>initialize()</code> est appelée au moment où l'on
-appuie sur le bouton «Exécuter». Vous pouvez l'utiliser pour choisir une
-zone plate. Comme avant, <code>step()</code> est appelée tous les dixièmes
-de seconde pour vous permettre d'ajuster la poussée (avec la fonction
-<code>[!java]void [/!]setPousseedesiree([!java]int
-[/!]poussee[!scala]:Integer[/!])</code>). Vous pouvez également contrôler
-l'angle du module avec la fonction <code>[!java]void
-[/!]setAngleDesire([!java]double [/!]angle[!scala]:Double[/!])</code>. Un
-angle de O° dénote une position verticale, avec le sommet du module dirigé
-vers le haut. C'est l'angle avec lequel vous devez vous poser. Un angle
-positif indique que le module penche vers la gauche tandis qu'un angle
-négatif indique au contraire qu'il penche à droite. Il est impossible de se
-pencher à plus de ±90°, et on ne peut pas pencher le module de plus de ±5°
-en une fois.</p>
-
-<p>Comme dans les exercices précédents, <code>[!java]List&lt;Point&gt;
-[/!]getSol()[!scala]:List[Point][/!]</code> retourne les points qui
-composent l'horizon. Le manuel de référence de votre module est disponible
-dans la documentation (Aide/À propos de ce monde).</p>
-
-<p>Comme d'habitude, votre programme doit se poser sans heurt dans toutes les
-situations que nous avons rencontré jusqu'à présent, ainsi que dans ce
-nouveau cas.</p>
-
-<p>Bonne chance. Essayez de ne pas vous scratcher ;)</p>
Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.html
===================================================================
--- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Fly the Lander!</h1>
-
-<p>After 30 days of staring at rocks and eating cereals you decide it's time to
-go explore other parts of the planet.</p>
-
-<p>You fly for a while and suddenly realize you're almost out of fuel.
-Unfortunately you're in a delicate situation and the autopilot is helpless.
-You will have to pilot the lander yourself. Your mission is to <b>land the
-lander on a flat zone with a vertical speed less than 10 m/s, an horizontal
-speed less than 5 m/s and an angle of 0°.</b></p>
-
-<p>You must define two functions: <code>[!java]void [/!]initialize()</code> and 
-<code>[!java]void [/!]step()</code>. <code>initialize()</code> is called once just 
-after you press "Run". You can use it to chose some flat zone. As before, 
-<code>step()</code> is called every 0.1 second and is used for adjusting the 
-lander's thrust and angle. As in the first exercise the lander's thrust is adjusted 
-via <code>[!java]void [/!]setDesiredThrust([!java]int [/!]desiredThrust[!scala]:Integer[/!])</code>. 
-But you can also control its angle via 
-<code>[!java]void [/!]setDesiredAngle([!java]double [/!]desiredAngle[!scala]:Double[/!])</code>. 
-An angle of 0° denotes a vertical position where the "head" of the lander points up. 
-This is the angle you must land with. A positive angle denotes a left-leaning lander, 
-a negative angle a right-leaning one. You cannot lean more than by ±90°, and the angle can vary by
-at most ±5° in one step.</p>
-
-<p>As in the previous exercise, <code>[!java]List&lt;Point&gt; [/!]getGround()[!scala]:List[Point][/!]</code> returns
-the vertices of the ground's profile from left to right. 
-Please refer to the documentation (Help/About this world) for a reference manual of your lunar lander.</p>
-
-<p>As before, your program must safely land the lander in all the situations
-encountered so far in addition to this new one.</p>
-
-<p>Good luck, try not to crash!</p>
Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.pt_BR.html
===================================================================
--- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.pt_BR.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h1>Fly the Lander!</h1>
-
-<p>After 30 days of staring at rocks and eating cereals you decide it's time to
-go explore other parts of the planet.</p>
-
-<p>You fly for a while and suddenly realize you're almost out of fuel.
-Unfortunately you're in a delicate situation and the autopilot is helpless.
-You will have to pilot the lander yourself. Your mission is to <b>land the
-lander on a flat zone with a vertical speed less than 10 m/s, an horizontal
-speed less than 5 m/s and an angle of 0°.</b></p>
-
-<p>You must define two functions: <code>[!java]void [/!]initialize()</code> and
-<code>[!java]void [/!]step()</code>. <code>initialize()</code> is called
-once just after you press "Run". You can use it to chose some flat zone. As
-before, <code>step()</code> is called every 0.1 second and is used for
-adjusting the lander's thrust and angle. As in the first exercise the
-lander's thrust is adjusted via <code>[!java]void
-[/!]setDesiredThrust([!java]int
-[/!]desiredThrust[!scala]:Integer[/!])</code>.  But you can also control its
-angle via <code>[!java]void [/!]setDesiredAngle([!java]double
-[/!]desiredAngle[!scala]:Double[/!])</code>.  An angle of 0° denotes a
-vertical position where the "head" of the lander points up.  This is the
-angle you must land with. A positive angle denotes a left-leaning lander, a
-negative angle a right-leaning one. You cannot lean more than by ±90°, and
-the angle can vary by at most ±5° in one step.</p>
-
-<p>As in the previous exercise, <code>[!java]List&lt;Point&gt;
-[/!]getGround()[!scala]:List[Point][/!]</code> returns the vertices of the
-ground's profile from left to right.  Please refer to the documentation
-(Help/About this world) for a reference manual of your lunar lander.</p>
-
-<p>As before, your program must safely land the lander in all the situations
-encountered so far in addition to this new one.</p>
-
-<p>Boa sorte, tente não cair!</p>
Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.scala
===================================================================
--- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLander.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package lessons.lander.lvl3_fly_the_lander
-
-import plm.core.model.lesson.ExerciseTemplated
-import plm.core.model.lesson.Lesson
-import lessons.lander.universe.DelegatingLanderWorld
-import lessons.lander.universe.Point
-import lessons.lander.universe.LanderEntity
-import lessons.lander.universe.Configurations._
-import Math.PI
-import scala.collection.JavaConversions._
-import lessons.lander.universe.LanderWorld
-import plm.universe.World
-
-class FlyTheLander(lesson: Lesson) extends ExerciseTemplated(lesson, null) {
-  tabName = "Lander"
-  setup(Array(
-      SIMPLE_TERRAIN_CHALLENGING_CONFIG,
-      CHALLENGING_TERRAIN_SIMPLE_CONFIG,
-      SIMPLE_TERRAIN_TRIVIAL_CONFIG))
-}
Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.java
===================================================================
--- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package lessons.lander.lvl3_fly_the_lander;
-
-import java.util.List;
-
-import lessons.lander.universe.LanderEntity;
-import lessons.lander.universe.Point;
-
-public class FlyTheLanderEntity extends LanderEntity {
-	/* BEGIN TEMPLATE */
-	/* BEGIN HIDDEN */
-	double targetStart;
-	double targetEnd;
-	/* END HIDDEN */
-	public void initialize() {
-		/* BEGIN HIDDEN */
-		List<Point> ground = getGround();
-		Point lastPoint = ground.get(0);
-		for (Point point: ground) {
-			if (point!=lastPoint && lastPoint.y() == point.y()) {
-				targetStart = lastPoint.x();
-				targetEnd = point.x();
-				return;
-			}
-			lastPoint = point;
-		}
-		/* END HIDDEN */
-	}
-
-	public void step() {
-		/* BEGIN SOLUTION */
-		if (getX() < targetStart) {
-			setDesiredAngle(-30);
-		} else if (getX() > targetEnd) {
-			setDesiredAngle(30);
-		} else {
-			if (getSpeedX() > 5) {
-				setDesiredAngle(25);
-			} else if (getSpeedX() < -5) {
-				setDesiredAngle(-25);
-			} else {
-				setDesiredAngle(0);
-			}
-		}
-		setDesiredThrust(getSpeedY() < -9 ? 4 : 3);
-		/* END SOLUTION */
-	}
-	/* END TEMPLATE */
-}
Index: b/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.py
===================================================================
--- a/src/lessons/lander/lvl3_fly_the_lander/FlyTheLanderEntity.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# BEGIN HIDDEN
-(startPos,endPos) = (0,0)
-# END HIDDEN
-
-# BEGIN TEMPLATE
-def initialize():
-    pass
-# BEGIN SOLUTION
-    global startPos
-    global endPos
-    lastPoint = getGround()[0]
-    for point in getGround():
-        if (point != lastPoint):
-            if lastPoint[1] == point[1]:
-                (startPos,endPos) = (lastPoint[0],point[0])
-        lastPoint = point
-# END SOLUTION
-
-def step():
-    pass
-# BEGIN HIDDEN
-    if (getX() < startPos):
-        setDesiredAngle(-30)
-    elif (getX() > endPos):
-        setDesiredAngle(30)
-    elif (getSpeedX() > 5):
-        setDesiredAngle(25)
-    elif (getSpeedX() < -5):
-        setDesiredAngle(-25)
-    else:
-        setDesiredAngle(0);
-        
-    if (getSpeedY() <-9):
-        setDesiredThrust(4)
-    else:
-        setDesiredThrust(3)
-
-# END HIDDEN
-
-# END TEMPLATE
-
-initialize()
-while isFlying():
-  step()
-  simulateStep()
Index: b/src/lessons/lander/lvl3_fly_the_lander/ScalaFlyTheLanderEntity.scala
===================================================================
--- a/src/lessons/lander/lvl3_fly_the_lander/ScalaFlyTheLanderEntity.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package lessons.lander.lvl3_fly_the_lander;
-
-import java.util.Iterator;
-import scala.collection.JavaConversions._
-
-import lessons.lander.universe._;
-
-class ScalaFlyTheLanderEntity extends LanderEntity {
-  /* BEGIN TEMPLATE */
-  /* BEGIN HIDDEN */
-  var targetStart=0.0
-  var targetEnd=0.0
-  /* END HIDDEN */
-  override def initialize() {
-    /* BEGIN HIDDEN */
-    var lastPoint:Point = getGround.get(0);
-    for (point <- getGround()) {
-      if (point != lastPoint) { // Avoid the loop when point is on the first element
-        if (point.y == lastPoint.y) {
-          targetStart = lastPoint.x
-          targetEnd = point.x
-        }
-      }
-      lastPoint = point
-    }
-    /* END HIDDEN */
-  }
-
-  override def step() {
-    /* BEGIN SOLUTION */
-    if (getX() < targetStart) {
-      setDesiredAngle(-30);
-    } else if (getX() > targetEnd) {
-      setDesiredAngle(30);
-    } else {
-      if (getSpeedX() > 5) {
-        setDesiredAngle(25);
-      } else if (getSpeedX() < -5) {
-        setDesiredAngle(-25);
-      } else {
-        setDesiredAngle(0);
-      }
-    }
-    
-    if (getSpeedY() < -9) {
-    	setDesiredThrust(4)
-    } else {
-    	setDesiredThrust(3);
-    }
-    /* END SOLUTION */
-  }
-  /* END TEMPLATE */
-}
Index: b/src/lessons/lander/short_desc.fr.html
===================================================================
--- a/src/lessons/lander/short_desc.fr.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h3>Alunisseur</h3>
-
-<p>Dans cette leçon, vous pilotez un alunisseur dans des situations de plus en
-plus complexes.</p>
-
-<p>Vous êtes supposé maîtriser les bases de la programmation et posséder
-quelques notions de mécanique du point avant de tenter cette leçon.</p>
Index: b/src/lessons/lander/short_desc.html
===================================================================
--- a/src/lessons/lander/short_desc.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h3>Lunar Lander</h3>
-
-<p>In this lesson you pilot a lunar landing module in increasingly complex
-situations.</p>
-
-<p>This lesson assumes some basic programming and physics skills.</p>
Index: b/src/lessons/lander/universe/DelegatingLanderWorld.fr.html
===================================================================
--- a/src/lessons/lander/universe/DelegatingLanderWorld.fr.html
+++ /dev/null
@@ -1,48 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h2>Alunisseur</h2>
-
-<p>Dans cet univers, vous contrôlez un module d'alunissage. À chaque pas de la
-simulation, vous avez accès à la position du module, sa vitesse, son angle
-et la poussée de son moteur. Vous devez alors décider de l'angle et de la
-poussée pour l'étape suivante. </p>
-
-<h2>Fonctions fournies</h2>
-
-<pre>[!java|c]double [/!]getX()[!scala]:Double[/!]
-[!java|c]double [/!]getY()[!scala]:Double[/!]</pre>
-Retourne la position en X et Y du module d'alunissage.
-<pre>[!java|c]double [/!]getVitesseX()[!scala]:Double[/!]
-[!java|c]double [/!]getVitesseY()[!scala]:Double[/!]</pre>
-Obtenir les vitesses horizontale et verticale du module.
-
-<pre>[!java|c]double [/!]getAngle()[!scala]:Double[/!]
-[!java|c]void [/!]setAngleDesire([!java|c]double [/!]angle[!scala]:Double[/!])</pre>
-Retourne ou fixe l'angle du module d'alunissage.<br/>
-Un angle de O° dénote une position verticale, avec le sommet du module
-dirigé vers le haut. C'est l'angle avec lequel vous devez vous poser. Un
-angle positif indique que le module penche vers la gauche tandis qu'un angle
-négatif indique au contraire qu'il penche à droite. Il est impossible de se
-pencher à plus de ±90°, et on ne peut pas pencher le module de plus de ±5°
-en une fois.
-
-<pre>[!java|c]int [/!]getPoussee()[!scala]:Int[/!]
-[!java|c]void [/!]setPousseeDesiree([!java|c]int [/!]poussée[!scala]:Int[/!])</pre>
-Retourne ou fixe la poussée du module. <br/>Vous ne pouvez incrémenter ou décrémenter la poussée que d'une unité à
-chaque fois. Si votre poussée actuelle est de 2 et que vous demandez une
-poussée de 4, vous n'obtiendrez que 3 au prochain pas de temps. Si vous
-demandez moins que 0 (ou plus que 4), tout se passera comme si vous
-demandiez 0 (ou 4).
-
-<pre>[!java|c]int [/!]getFuel()[!scala]:Int[/!]</pre>
-Obtient la quantité de fuel restant dans le réservoir. À chaque pas de
-simulation, le module consomme entre 0 et 4 unités de fuel, en fonction de
-sa poussée. Une fois que vous avez utilisé tout votre carburant, vous êtes
-en chute libre alors prenez garde !
-
-<pre>[!java]List&lt;Point&gt; [/!]getSol()[! scala]:List[Point][/!]</pre>
-Obtenir les points du sol de gauche à droite. [!java|scala]Vous pouvez
-retrouver les coordonnées X et Y de chaque point avec les méthodes
-correspondantes de votre point : <code>p.x()</code> et
-<code>p.y()</code>.[/!] [!python]Chaque point est un tableau de deux entiers
-représentant respectivement les coordonnées X et Y de chaque point.[/!]
\ No newline at end of file
Index: b/src/lessons/lander/universe/DelegatingLanderWorld.html
===================================================================
--- a/src/lessons/lander/universe/DelegatingLanderWorld.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h2>Lunar Lander</h2>
-
-<p>In this universe you pilot a lunar lander. At each simulation step you're
-given the lander's position, speed, angle and thrust and must issue a command
-adjusting its angle and thrust.</p>
-
-<h2>Provided functions</h2>
-
-<pre>[!java|c]double [/!]getX()[!scala]:Double[/!]
-[!java|c]double [/!]getY()[!scala]:Double[/!]</pre>
-Get the X and Y position of the lander.
-<pre>[!java|c]double [/!]getSpeedX()[!scala]:Double[/!]
-[!java|c]double [/!]getSpeedY()[!scala]:Double[/!]</pre>
-Get the horizontal and vertical speed of the lander.
-
-<pre>[!java|c]double [/!]getAngle()[!scala]:Double[/!]
-[!java|c]void [/!]setDesiredAngle([!java|c]double [/!]desiredAngle[!scala]:Double[/!])</pre>
-Get or set the angle of the lander.<br/>
-An angle of 0° denotes a vertical position where the "head" of the lander points up. 
-This is the angle you must land with. A positive angle denotes a left-leaning lander, 
-a negative angle a right-leaning one. You cannot lean more than by ±90°, and the angle can vary by
-at most ±5° in one step.
-
-<pre>[!java|c]int [/!]getThrust()[!scala]:Int[/!]
-[!java|c]void [/!]setDesiredThrust([!java|c]int [/!]thrust[!scala]:Int[/!])</pre>
-Get or set the thrust of the lander. <br/>You can only 
-increment or decrement the thrust by 1 between two simulation steps, so if the 
-current thrust is 2 and you ask for 4, you'll only get 3 in the next step. If 
-you ask for less than 0 (resp. more than 4), everything will be as if you had 
-asked for 0 (resp. 4).
-
-<pre>[!java|c]int [/!]getFuel()[!scala]:Int[/!]</pre>
-Get the remaining fuel in the lander.  At each step of the simulation the lander 
-consumes as many fuel units as the current thrust. Once you run out of fuel you're 
-in free fall so beware!
-
-<pre>[!java]List&lt;Point&gt; [/!]getGround()[! scala]:List[Point][/!]</pre>
-Get the vertices of the ground's profile from left to right. 
-[!java|scala]You can retrieve the X and Y coordinates of each point
-with the corresponding methods of your point: <code>p.x()</code> and
-<code>p.y()</code>.[!/]
-[!python]Each point is an array of two integers denoting respectively
-the X and Y coordinates of that point.[/!]
\ No newline at end of file
Index: b/src/lessons/lander/universe/DelegatingLanderWorld.java
===================================================================
--- a/src/lessons/lander/universe/DelegatingLanderWorld.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package lessons.lander.universe;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-import javax.swing.ImageIcon;
-
-import plm.core.lang.ProgrammingLanguage;
-import plm.core.ui.WorldView;
-import plm.universe.World;
-import scala.collection.immutable.List;
-
-public class DelegatingLanderWorld extends World {
-
-  final LanderWorld realWorld;
-
-  public DelegatingLanderWorld(String name, int width, int height,
-      List<Point> ground, Point position, Point speed, double angle, int thrust, int fuel) {
-    super(name);
-    realWorld = new LanderWorld(this);
-    realWorld.width_$eq(width);
-    realWorld.height_$eq(height);
-    realWorld.ground_$eq(ground);
-    realWorld.position_$eq(position);
-    realWorld.speed_$eq(speed);
-    realWorld.angle_$eq(angle);
-    realWorld.thrust_$eq(thrust);
-    realWorld.fuel_$eq(fuel);
-  }
-
-  public DelegatingLanderWorld(DelegatingLanderWorld world) {
-    super(world.getName());
-    realWorld = new LanderWorld(this);
-    reset(world);
-  }
-
-  @Override
-  public ImageIcon getIcon() {
-    return realWorld.getIcon();
-  }
-
-  @Override
-  public void setupBindings(ProgrammingLanguage lang, ScriptEngine engine) throws ScriptException {
-    realWorld.setupBindings(lang, engine);
-  }
-
-  @Override
-  public boolean winning(World target) {
-    return realWorld.winning(target);
-  }
-
-  @Override
-  public String diffTo(World world) {
-    return realWorld.diffTo(world);
-  }
-
-  @Override
-  public void reset(World initialWorld) {
-    realWorld.reset(((DelegatingLanderWorld) initialWorld).realWorld);
-    super.reset(initialWorld);
-  }
-
-  @Override
-  public WorldView getView() {
-    return realWorld.getView();
-  }
-
-  @Override
-  public String toString() {
-    return realWorld.toString();
-  }
-}
Index: b/src/lessons/lander/universe/DelegatingLanderWorld.pt_BR.html
===================================================================
--- a/src/lessons/lander/universe/DelegatingLanderWorld.pt_BR.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-<!-- Please don't translate this file but l10n/missions/plm.pot (see https://github.com/oster/PLM/wiki/Working-on-translations) -->
-<h2>Lunar Lander</h2>
-
-<p>In this universe you pilot a lunar lander. At each simulation step you're
-given the lander's position, speed, angle and thrust and must issue a
-command adjusting its angle and thrust.</p>
-
-<h2>Provided functions</h2>
-
-<pre>[!java|c]double [/!]getX()[!scala]:Double[/!]
-[!java|c]double [/!]getY()[!scala]:Double[/!]</pre>
-Obter (Get) as posições X e Y do "lander".
-<pre>[!java|c]double [/!]getVelocidadeX()[!scala]:Double[/!]
-[!java|c]double [/!]getVelocidadeY()[!scala]:Double[/!]</pre>
-Get the horizontal and vertical speed of the lander.
-
-<pre>[!java|c]double [/!]getÂngulo()[!scala]:Double[/!]
-[!java|c]void [/!]setÂnguloDesejado([!java|c]double [/!]ÂnguloDesejado[!scala]:Double[/!])</pre>
-Get or set the angle of the lander.<br/>
-An angle of 0° denotes a vertical position where the "head" of the lander
-points up.  This is the angle you must land with. A positive angle denotes a
-left-leaning lander, a negative angle a right-leaning one. You cannot lean
-more than by ±90°, and the angle can vary by at most ±5° in one step.
-
-<pre>[!java|c]int [/!]getImpulso()[!scala]:Int[/!]
-[!java|c]void [/!]setImpulsoDesejado([!java|c]int [/!]thrust[!scala]:Int[/!])</pre>
-Get or set the thrust of the lander. <br/>You can only increment or decrement the thrust by 1 between two simulation
-steps, so if the current thrust is 2 and you ask for 4, you'll only get 3 in
-the next step. If you ask for less than 0 (resp. more than 4), everything
-will be as if you had asked for 0 (resp. 4).
-
-<pre>[!java|c]int [/!]getCombustível()[!scala]:Int[/!]</pre>
-Get the remaining fuel in the lander.  At each step of the simulation the
-lander consumes as many fuel units as the current thrust. Once you run out
-of fuel you're in free fall so beware!
-
-<pre>[!java]List&lt;Point&gt; [/!]getChão()[! scala]:List[Point][/!]</pre>
-Get the vertices of the ground's profile from left to right.
-[!java|scala]You can retrieve the X and Y coordinates of each point with the
-corresponding methods of your point: <code>p.x()</code> and
-<code>p.y()</code>.[!/] [!python]Each point is an array of two integers
-denoting respectively the X and Y coordinates of that point.[/!]
\ No newline at end of file
Index: b/src/plm/core/ui/ChooseLessonDialog.java
===================================================================
--- a/src/plm/core/ui/ChooseLessonDialog.java
+++ b/src/plm/core/ui/ChooseLessonDialog.java
@@ -78,7 +78,7 @@ public class ChooseLessonDialog extends
 				{"lessons/welcome", "lessons/maze", "lessons/turmites", "lessons/turtleart"},
 				{"lessons/sort/basic", "lessons/sort/dutchflag", "lessons/sort/baseball", "lessons/sort/pancake"},
 				{"lessons/recursion/cons", "lessons/recursion", "lessons/recursion/hanoi" },
-				{"lessons/lightbot", "lessons/bat/string1", "lessons/lander" },
+				{"lessons/lightbot", "lessons/bat/string1" },
 		    }); 
 	
 
Index: b/src/plm/test/ExoTest.java
===================================================================
--- a/src/plm/test/ExoTest.java
+++ b/src/plm/test/ExoTest.java
@@ -39,7 +39,7 @@ public class ExoTest {
 		"lessons.sort.basic", "lessons.sort.dutchflag", "lessons.sort.baseball", "lessons.sort.pancake", 
 		"lessons.recursion.cons", "lessons.recursion", "lessons.recursion.hanoi",
 		// "lessons.lightbot", // Well, testing this requires testing the swing directly I guess
-		"lessons.bat.string1", "lessons.lander",
+		"lessons.bat.string1",
 		};
 
 	@BeforeClass
@@ -122,7 +122,7 @@ public class ExoTest {
 			// For compiled languages, we mutate to the compiled entity. 
 			// For script languages, we mutate to the correction entity.
 			StudentOrCorrection what = StudentOrCorrection.CORRECTION;
-			if (lang == Game.JAVA || lang == Game.SCALA || lang == Game.C)
+			if (lang == Game.JAVA || lang == Game.C)
 				what = StudentOrCorrection.STUDENT;
 			exo.mutateEntities(WorldKind.CURRENT, what);
 			
@@ -157,14 +157,7 @@ public class ExoTest {
 	public void testJavaEntity() {
 		testCorrectionEntity(Game.JAVA);
 	}
-	
-	@Test(timeout=30000) // The compiler sometimes takes time to kick in 
-	public void testScalaEntity() {
-		if (!exo.getProgLanguages().contains(Game.SCALA)) 
-			fail("Exercise "+exo.getId()+" does not support scala");
-		testCorrectionEntity(Game.SCALA);
-	}
-	
+		
 //	@Test(timeout=30000) // The compiler sometimes takes time to kick in 
 	public void testCEntity() {
 		if (!exo.getProgLanguages().contains(Game.C)) 
Index: b/src/plm/test/LessonTest.java
===================================================================
--- a/src/plm/test/LessonTest.java
+++ b/src/plm/test/LessonTest.java
@@ -30,7 +30,7 @@ public class LessonTest {
 		"lessons.sort.basic", "lessons.sort.dutchflag", "lessons.sort.baseball", "lessons.sort.pancake", 
 		"lessons.recursion.cons", "lessons.recursion", "lessons.recursion.hanoi",
 		// "lessons.lightbot", // Well, testing this requires testing the swing directly I guess
-		"lessons.bat.string1", "lessons.lander",
+		"lessons.bat.string1",
 		};
 	
 	private String lessonName;
@@ -82,13 +82,7 @@ public class LessonTest {
 		Lesson lesson = loadLesson(Game.JAVA);
 		assertTrue("An error arose while loading lesson "+lesson.getName()+"...", lesson.getLoadingOutcomeState() == LoadingOutcome.SUCCESS);
 	}
-	
-	@Test
-	public void testScalaLesson() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
-		Lesson lesson = loadLesson(Game.SCALA);
-		assertTrue("An error arose while loading lesson "+lesson.getName()+"...", lesson.getLoadingOutcomeState() == LoadingOutcome.SUCCESS);
-	}
-	
+		
 	@Test
 	public void testPythonLesson() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
 		Lesson lesson = loadLesson(Game.PYTHON);
Index: b/src/plm/core/lang/LangScala.java
===================================================================
--- a/src/plm/core/lang/LangScala.java
+++ /dev/null
@@ -1,247 +0,0 @@
-package plm.core.lang;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Vector;
-
-import plm.core.PLMCompilerException;
-import plm.core.model.Game;
-import plm.core.model.LogWriter;
-import plm.core.model.lesson.ExecutionProgress;
-import plm.core.model.lesson.Exercise;
-import plm.core.model.lesson.Exercise.StudentOrCorrection;
-import plm.core.ui.ResourcesCache;
-import plm.universe.Entity;
-import scala.Option;
-import scala.collection.JavaConverters;
-import scala.reflect.internal.util.BatchSourceFile;
-import scala.reflect.internal.util.Position;
-import scala.reflect.internal.util.SourceFile;
-import scala.reflect.io.VirtualDirectory;
-import scala.reflect.io.VirtualFile;
-import scala.tools.nsc.Global;
-import scala.tools.nsc.Global.Run;
-import scala.tools.nsc.Settings;
-import scala.tools.nsc.interpreter.AbstractFileClassLoader;
-import scala.tools.nsc.reporters.AbstractReporter;
-
-public class LangScala extends JVMCompiledLang {
-
-	ScalaCompiler compiler = new ScalaCompiler();
-	
-	public LangScala() {
-		super("Scala","scala",ResourcesCache.getIcon("img/lang_scala.png"));
-	}
-
-	@Override
-	public void compileExo(Exercise exo, LogWriter out, StudentOrCorrection whatToCompile) 
-			throws PLMCompilerException {
-		/* Make sure each run generate a new package to avoid that the loader cache prevent the reloading of the newly generated class */
-		packageNameSuffix++;
-		runtimePatterns.put("\\$package", 
-				"package "+packageName()+";import java.awt.Color;");
-
-		List<plm.core.model.session.SourceFile> sfs = exo.getSourceFilesList(this);
-		if (sfs == null || sfs.isEmpty()) {
-			String msg = exo.getName()+": No source to compile";
-			System.err.println(msg);
-			PLMCompilerException e = new PLMCompilerException(msg, null, null);
-			exo.lastResult = ExecutionProgress.newCompilationError(e.getMessage());				
-			throw e;
-		}
-
-		try {
-			compiler.reset();
-			for (plm.core.model.session.SourceFile sf : sfs) {
-				compiler.compile(className(sf.getName()), sf.getCompilableContent(runtimePatterns,whatToCompile), sf.getOffset());
-			}
-		} catch (PLMCompilerException e) {
-			System.err.println(Game.i18n.tr("Compilation error:"));
-			System.err.println(e.getMessage());
-			exo.lastResult = ExecutionProgress.newCompilationError(e.getMessage());
-
-			throw e;
-		}
-		
-	}
-	
-	/** Converts {@code "foo.bar.baz"} to {@code "foo.bar.Scalabaz"}. */
-	@Override
-	public String nameOfCorrectionEntity(Exercise exo){
-		String path = super.nameOfCorrectionEntity(exo);
-		
-		String[] components = path.split("\\.");
-		StringBuilder result = new StringBuilder();
-		int last = components.length - 1;
-		for (int i = 0; i < last; i++) {
-			result.append(components[i] + ".");
-		}
-		result.append("Scala" + components[last]);
-		return result.toString();
-	}
-
-	@Override
-	protected Entity mutateEntity(String newClassName)
-			throws InstantiationException, IllegalAccessException,
-			ClassNotFoundException {
-		return (Entity) compiler.findClass(className(newClassName)).newInstance();
-	}
-}
-
-/** In memory compiler of scala code. 
- *  This is highly inspired of https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala */
-class ScalaCompiler {
-	
-	private PLMReporter reporter;
-	private Settings settings;
-	private Map<String, Class<?>> cache = new HashMap<String, Class<?>>();
-	private Global global;
-	private VirtualDirectory target;
-	private ClassLoader classLoader = new AbstractFileClassLoader(target, this.getClass().getClassLoader());
-	
-	public ScalaCompiler() {
-		super();
-		settings = new Settings();
-		settings.nowarnings().tryToSetFromPropertyValue("true"); // warnings seem to be exceptions, and we don't want them to mess with us
-
-		Option<VirtualDirectory> noAncestor = scala.Option$.MODULE$.apply(null);
-		target = new VirtualDirectory("(memory)", noAncestor);
-		settings.outputDirs().setSingleOutput(target);
-		
-		settings.usejavacp().tryToSetFromPropertyValue("true");
-		//settings.usemanifestcp().tryToSetFromPropertyValue("true");
-		reporter = new PLMReporter(settings);
-		global = new Global(settings,reporter);
-	}
-
-	public void reset() {
-		reporter.reset();
-		reporter.setOffset(0);
-		target.clear();
-		cache = new HashMap<String, Class<?>>();
-		classLoader = new AbstractFileClassLoader(target, this.getClass().getClassLoader());
-	}
-
-	public void compile(String name,String content,int offset) throws PLMCompilerException {
-		if (Game.getInstance().isDebugEnabled()) 
-			System.out.println("Compiline souce "+name+" to scala (offset:"+offset+"):\n"+content);
-		
-		Run compiler = global.new Run();
-		List<SourceFile> sources = new LinkedList<SourceFile>();
-		
-		sources.add(new BatchSourceFile(new VirtualFile(name) , content.toCharArray()));
-		reporter.setOffset(offset);
-		
-		compiler.compileSources(JavaConverters.asScalaBufferConverter(sources).asScala().toList());
-		
-		if (Game.getInstance().isDebugEnabled() && reporter.hasErrors())
-			System.out.println("Here is the scala source code of "+name+" (offset:"+offset+"): "+content);
-		reporter.throwExceptionOnNeed();
-	}
-	public Class<?> findClass(String className) {
-		synchronized (this) {
-			if (!cache.containsKey(className)) {
-				Class<?> res;
-				try {
-					res = classLoader.loadClass(className);
-				} catch (ClassNotFoundException e) {
-					res = null;
-				}
-				cache.put(className, res);
-			}
-
-			return cache.get(className);			
-		}
-	}
-	
-	class PLMReporter extends AbstractReporter {
-		final static int INFO = 0;
-		final static int WARNING = 1;
-		final static int ERROR = 2;
-		int offset=0;
-		Vector<String> messages = new Vector<String>();
-		Settings settings;
-
-		public PLMReporter(Settings s) {
-			settings = s;
-		}
-		public void setOffset(int _offset) {
-			this.offset = _offset;
-		}
-		@Override
-		public Settings settings() {
-			return settings;
-		}
-		@Override
-		public void displayPrompt() { 
-			/* Don't do that, pal. */ 
-		}
-		@Override
-		public void display(Position pos, String message, Severity _severity) {
-			String severityName = _severity.toString(); 
-			String label = "";
-			int severity = -1;
-			if (severityName.equals("INFO") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity@0"))
-				severity = INFO;
-			if (severityName.equals("WARNING") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity@1")) {
-				severity = WARNING;
-				label= "warning: ";
-			}
-			if (severityName.equals("ERROR") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity@2")) {
-				severity = ERROR;
-				label = "error: ";
-			}
-			if (severity == -1)
-				throw new RuntimeException("Got an unknown severity: "+severityName+". Please adapt the PLM to this new version of scala (or whatever).");
-			if (severity == INFO && !Game.getInstance().isDebugEnabled()) 
-				return;
-
-			int lineNum = -1;
-			try {
-				lineNum = pos.line() - offset;
-			} catch (Throwable t) {
-				// That's fine if the line number is not defined.
-			}
-
-			String name = pos.source().path();
-			int lastDot = name.lastIndexOf('.');
-			if (lastDot != -1)
-				name = name.substring(lastDot+1);
-			String msg = name+(lineNum == -1? "": ":"+lineNum) +": "+label+message;
-
-			// Append the line content and a position marker, if possible
-			if (pos != null && pos.isDefined()) {
-				msg += "\n"+pos.inUltimateSource(pos.source()).lineContent()+"\n";
-				for (int i=0;i<pos.column()-1;i++)
-					msg += " ";
-				msg += "^";
-			}
-
-			messages.add(msg);
-		}
-		public void throwExceptionOnNeed() throws PLMCompilerException {
-			if (hasErrors()) {
-				StringBuffer sb = new StringBuffer();
-				for (String s : messages)
-					sb.append(s);
-				throw new PLMCompilerException(sb.toString(), null, null);
-			}
-		}
-		@Override
-		public void reset() {
-			super.reset();
-			messages.removeAllElements();
-		}
-		
-		/* These methods are mandated by scala 2.11, but I dunno what to do with it, so ignore that for now */
-		public int count(Object o) {
-			return 0;
-		}
-		public void resetCount(Object o) {}
-		public void info0(Position arg0, String arg1, Object arg2, boolean arg3) {
-			// TODO Auto-generated method stub
-		}
-	}
-}
\ No newline at end of file
Index: b/src/plm/core/model/Game.java
===================================================================
--- a/src/plm/core/model/Game.java
+++ b/src/plm/core/model/Game.java
@@ -43,7 +43,6 @@ import plm.core.lang.LangJava;
 import plm.core.lang.LangLightbot;
 import plm.core.lang.LangPython;
 import plm.core.lang.LangRuby;
-import plm.core.lang.LangScala;
 import plm.core.lang.ProgrammingLanguage;
 import plm.core.model.lesson.Exercise;
 import plm.core.model.lesson.Exercise.WorldKind;
@@ -99,14 +98,13 @@ public class Game implements IWorldView
 
 	public static final ProgrammingLanguage JAVA =       new LangJava();
 	public static final ProgrammingLanguage PYTHON =     new LangPython();
-	public static final ProgrammingLanguage SCALA =      new LangScala();
 	public static final ProgrammingLanguage C =          new LangC();
 	//public static final ProgrammingLanguage JAVASCRIPT = new ProgrammingLanguage("JavaScript","js",ResourcesCache.getIcon("img/lang_javascript.png"));
 	public static final ProgrammingLanguage RUBY =       new LangRuby();
 	public static final ProgrammingLanguage LIGHTBOT =   new LangLightbot();
 	
 	public static final ProgrammingLanguage[] programmingLanguages = new ProgrammingLanguage[] {
-		JAVA, PYTHON, SCALA, RUBY, LIGHTBOT, C // TODO: re-add JAVASCRIPT to this list once it works at least a bit
+		JAVA, PYTHON, RUBY, LIGHTBOT, C // TODO: re-add JAVASCRIPT to this list once it works at least a bit
 	}; 
 	private ProgrammingLanguage programmingLanguage = JAVA;
 
@@ -164,10 +162,6 @@ public class Game implements IWorldView
 		i18n = I18nFactory.getI18n(getClass(),"org.plm.i18n.Messages",FileUtils.getLocale(), I18nFactory.FALLBACK);
 		loadProperties();
 
-		if (checkScala())
-			System.err.println(i18n.tr("Scala is usable on your machine. Congratulations."));
-		else
-			System.err.println(i18n.tr("Please install Scala version 2.10 or higher to use it in the PLM."));
 		if (checkPython())
 			System.err.println(i18n.tr("Jython is usable on your machine. Congratulations."));
 		else
@@ -180,17 +174,13 @@ public class Game implements IWorldView
 		String defaultProgrammingLanguage = Game.getProperty(PROP_PROGRAMING_LANGUAGE,Game.JAVA.getLang(),true);
 		if (!defaultProgrammingLanguage.equalsIgnoreCase(Game.JAVA.getLang()) &&
 				!defaultProgrammingLanguage.equalsIgnoreCase(Game.PYTHON.getLang()) &&
-				!defaultProgrammingLanguage.equalsIgnoreCase(Game.SCALA.getLang()) && 
 				!defaultProgrammingLanguage.equalsIgnoreCase(Game.C.getLang())) 
 			System.err.println(i18n.tr("Warning, the default programming language is neither ''Java'' nor ''python'' or ''Scala'' or ''C'' but {0}.\n"+
 					"   This language will be used to setup the worlds, possibly leading to severe issues for the exercises that don''t expect it.\n" +
 					"   It is safer to change the current language, and restart the PLM before proceeding.\n"+
 					"   Alternatively, the property {1} can be changed in your configuration file ({2}/plm.properties)",defaultProgrammingLanguage,PROP_PROGRAMING_LANGUAGE, getSavingLocation()));
 
-		if (defaultProgrammingLanguage.equalsIgnoreCase(Game.SCALA.getLang()) && !canScala) {
-			System.err.println(i18n.tr("The default programming language is Scala, but your scala installation is not usable. Switching to Java instead.\n"));
-			setProgramingLanguage(JAVA);
-		} else if (defaultProgrammingLanguage.equalsIgnoreCase(Game.PYTHON.getLang()) && !canPython) {
+	        if (defaultProgrammingLanguage.equalsIgnoreCase(Game.PYTHON.getLang()) && !canPython) {
 			System.err.println(i18n.tr("The default programming language is python, but your python installation is not usable. Switching to Java instead.\n"));
 			setProgramingLanguage(JAVA);
 		} else if (defaultProgrammingLanguage.equalsIgnoreCase(Game.C.getLang()) && !canC) {
@@ -231,35 +221,7 @@ public class Game implements IWorldView
 
 	@SuppressWarnings({ "rawtypes", "unchecked" })
 	private boolean checkScala() {
-		String[] resources = new String[] {"/scala/tools/nsc/Interpreter", "/scala/ScalaObject", "/scala/reflect/io/AbstractFile"};
-		String[] hints     = new String[] {"scala-compiler.jar",           "scala-library.jar",  "scala-reflect.jar"};
-		for (int i=0;i<resources.length;i++) {
-			scalaError = canResolve(resources[i],hints[i]);
-			if (!scalaError.isEmpty()) {
-				System.err.println(scalaError);
-				return canScala;
-			}
-		}
-
-		String version = null;
-		try {
-			Class props = Class.forName("scala.util.Properties");
-			Method meth = props.getMethod("versionString", new Class[] {});
-			version = (String) meth.invoke(props);
-		} catch (Exception e) {
-			scalaError = i18n.tr("Error {0} while retrieving the Scala version: {1}", e.getClass().getName() ,e.getLocalizedMessage());
-			System.err.println( scalaError );
-			return canScala;
-		}
-
-		if (version.contains("version 2.10") || version.contains("version 2.11")) {
-			canScala = true;
-			return canScala;
-		} else {
-			scalaError = i18n.tr("Scala is too ancient. Found {0} while I need 2.10 or higher.",version);
-			System.err.println(scalaError);
-			return canScala;
-		}
+	        return false;
 	}
 
 	public boolean canPython = false;
@@ -972,11 +934,6 @@ public class Game implements IWorldView
 
 		if (isValidProgLanguage(newLanguage)) {
 			//System.out.println("Switch programming language to "+newLanguage);
-			if (newLanguage.equals(Game.SCALA) && !canScala) {
-				JOptionPane.showMessageDialog(null, i18n.tr("Please install Scala version 2.10 or higher to use it in the PLM.\n\n")+scalaError ,
-						i18n.tr("Scala is missing"), JOptionPane.ERROR_MESSAGE); 
-				return;
-			}
 			if (newLanguage.equals(Game.PYTHON) && !canPython) {
 				JOptionPane.showMessageDialog(null, i18n.tr("Please install jython and its dependencies to use the python programming language in the PLM.\n\n")+pythonError,
 						i18n.tr("Python is missing"), JOptionPane.ERROR_MESSAGE); 
@@ -999,7 +956,7 @@ public class Game implements IWorldView
 			}
 			this.programmingLanguage = newLanguage;
 			fireProgLangChange(newLanguage);
-			if (newLanguage.equals(Game.JAVA) || newLanguage.equals(Game.PYTHON) || newLanguage.equals(Game.SCALA) || newLanguage.equals(Game.C)) // Only save it if it's stable enough
+			if (newLanguage.equals(Game.JAVA) || newLanguage.equals(Game.PYTHON) || newLanguage.equals(Game.C)) // Only save it if it's stable enough
 				setProperty(PROP_PROGRAMING_LANGUAGE, newLanguage.getLang());
 			return;
 		}
Index: b/src/plm/core/model/lesson/ExerciseTemplated.java
===================================================================
--- a/src/plm/core/model/lesson/ExerciseTemplated.java
+++ b/src/plm/core/model/lesson/ExerciseTemplated.java
@@ -212,7 +212,7 @@ public abstract class ExerciseTemplated
 		String initialContent = templateHead.toString() + templateTail.toString();
 		String skelContent;
 		String headContent;
-		if (lang == Game.PYTHON || lang == Game.SCALA || lang == Game.C) { 
+		if (lang == Game.PYTHON || lang == Game.C) { 
 			skelContent = skel.toString();
 			headContent = head.toString();
 		} else {
@@ -358,7 +358,7 @@ public abstract class ExerciseTemplated
 						System.out.println("Found suitable templating entity "+lang.nameOfCorrectionEntity(this)+" in "+lang);
 
 				} catch (NoSuchEntityException e) {
-					if (lang.equals(Game.PYTHON) || lang.equals(Game.SCALA) || lang.equals(Game.JAVA)) 
+					if (lang.equals(Game.PYTHON) || lang.equals(Game.JAVA)) 
 						System.out.println("No templating entity found: "+e);
 						
 					if (getProgLanguages().contains(lang)) 
Index: b/src/plm/universe/bat/BatTest.java
===================================================================
--- a/src/plm/universe/bat/BatTest.java
+++ b/src/plm/universe/bat/BatTest.java
@@ -165,9 +165,7 @@ public class BatTest {
 	}
 	private void displayParameter(Object o, StringBuffer sb, ProgrammingLanguage pl) {
 		if (o == null) {
-			if (pl == Game.SCALA)
-				sb.append("Nil");
-			else if (pl == Game.PYTHON)
+			if (pl == Game.PYTHON)
 				sb.append("None");
 			else
 				sb.append("null");
@@ -175,8 +173,6 @@ public class BatTest {
 		} else if (o instanceof String[]) {
 			if (pl.equals(Game.JAVA)) {
 				sb.append("{");
-			} else if (pl.equals(Game.SCALA)) {
-				sb.append("Array(");
 			} else if (pl.equals(Game.PYTHON)) { 
 				sb.append("[");
 			} else {
@@ -191,8 +187,6 @@ public class BatTest {
 			sb.deleteCharAt(sb.length()-1);
 			if (pl.equals(Game.JAVA)) {
 				sb.append("}");
-			} else if (pl.equals(Game.SCALA)) {
-				sb.append(")");
 			} else if (pl.equals(Game.PYTHON)) { 
 				sb.append("]");
 			} else {
@@ -204,8 +198,6 @@ public class BatTest {
 			
 			if (pl.equals(Game.JAVA)) {
 				sb.append("{");
-			} else if (pl.equals(Game.SCALA)) {
-				sb.append("Array(");
 			} else if (pl.equals(Game.PYTHON)) { // Python
 				sb.append("[");
 			} else {
@@ -231,8 +223,6 @@ public class BatTest {
 			}
 			if (pl.equals(Game.JAVA)) {
 				sb.append("}");
-			} else if (pl.equals(Game.SCALA)) {
-				sb.append(")");
 			} else if (pl.equals(Game.PYTHON)) { 
 				sb.append("]");
 			} else {
@@ -240,7 +230,7 @@ public class BatTest {
 			}
 		} else if (o instanceof Boolean) {
 			Boolean b = (Boolean) o;
-			if (pl.equals(Game.JAVA) || pl.equals(Game.SCALA)) {
+			if (pl.equals(Game.JAVA)) {
 				sb.append(b ? "true":"false");
 			} else if (pl.equals(Game.PYTHON)) { 
 				sb.append(b ? "True" : "False");
@@ -296,8 +286,6 @@ public class BatTest {
 			displayParameter(o, sb, Game.getProgrammingLanguage());
 			return sb.toString();
 		} else {
-			if (Game.getProgrammingLanguage() == Game.SCALA)
-				return "Nil";
 			if (Game.getProgrammingLanguage() == Game.PYTHON)
 				return "None";
 			return "null";
Index: b/src/plm/test/simple/test/ScalaSimpleExerciseTest.java
===================================================================
--- a/src/plm/test/simple/test/ScalaSimpleExerciseTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package plm.test.simple.test;
-
-import plm.core.model.Game;
-
-public class ScalaSimpleExerciseTest extends JVMCompiledSimpleExerciseTest {
-	
-	public ScalaSimpleExerciseTest() {
-		super(Game.SCALA);
-	}
-	
-	@Override
-	public String generateSyntaxErrorCode() {
-		return "zqkdçajdé\"\"";
-	}
-
-	@Override
-	public String generateVariableErrorCode() {
-		return "toto += 1;\n";
-	}
-
-	@Override
-	public String generateNullPointerErrorCode() {
-		return "override def run() {\n"
-				+ "  var s:String = null;\n"
-				+ "  println(s.length());\n"
-				+ "}";
-	}
-
-	@Override
-	public String generateOutOfBoundsErrorCode() {
-		return "override def run() {\n"
-				+ "  var t:Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);\n"
-				+ "  println(t(42));\n"
-				+ "}";
-	}
-
-	@Override
-	public String generateWrongCode() {
-		return "override def run() {\n"
-				+ "  world.asInstanceOf[SimpleWorld].setObjectif(false);\n"
-				+ "}";
-	}
-
-	@Override
-	public String generateSolutionFollowedByError() {
-		return "override def run() {\n"
-				+ "  world.asInstanceOf[SimpleWorld].setObjectif(true);\n"
-				+ "  var t:Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);\n"
-				+ "  println(t(42));\n"
-				+ "}";
-	}
-}
Index: b/src/plm/core/lang/JVMCompiledLang.java
===================================================================
--- a/src/plm/core/lang/JVMCompiledLang.java
+++ b/src/plm/core/lang/JVMCompiledLang.java
@@ -48,15 +48,6 @@ public abstract class JVMCompiledLang ex
 					ent = (Entity)getClass().getClassLoader().loadClass(newClassName).newInstance(); 
 				} catch (Exception e2) {
 					if (whatToMutate == StudentOrCorrection.STUDENT) {
-						if (Game.getProgrammingLanguage() == Game.SCALA)
-							throw new PLMCompilerException(Game.i18n.tr(
-									  "Your entity failed to start. Did you forgot to put your code within a method?\n\n"
-									+ "This problem often arises when the exercise expects you to put all the code within a \n"
-									+ "method e.g. run(), but you put some statements (e.g. forward()) outside of any method.\n\n"
-									+ "The easiest solution to sort it out is to copy all your code (Ctrl-A Ctrl-C), use the \n"
-									+ "'Exercise/Revert' menu to reset the template, and paste (Ctrl-V) your code within the\n"
-									+ "provided method."));
-						else
 							throw new PLMCompilerException(Game.i18n.tr("Your entity failed to start. Your constructor seems to be broken, but I have no clue."));
 					} else {
 						throw new PLMEntityNotFound("Cannot find an entity of name "+className(newClassName)+" or "+newClassName+". Broken lesson.", e2);
Index: b/src/plm/core/model/lesson/ExerciseTemplatingEntity.java
===================================================================
--- a/src/plm/core/model/lesson/ExerciseTemplatingEntity.java
+++ b/src/plm/core/model/lesson/ExerciseTemplatingEntity.java
@@ -83,19 +83,7 @@ public abstract class ExerciseTemplating
 		javaFile.setCorrection("$package "+template+" @SuppressWarnings(\"unchecked\") public void run(BatTest t) {\n"+javaFile.getTemplate()+"}\n"+javaFile.getCorrection()+" }");
 		javaFile.setTemplate  ("$package "+template+" @SuppressWarnings(\"unchecked\") public void run(BatTest t) {  "+javaFile.getTemplate()+"}    $body }");
 		//System.out.println("New template: "+sf.getTemplate());
-		
-		if (getProgLanguages().contains(Game.SCALA)) {
-			SourceFile scalaFile = sourceFiles.get(Game.SCALA).get(0);
-			String header = "$package\n"
-					+ "import plm.universe.bat.{BatEntity,BatWorld,BatTest}; \n"
-					+ "import plm.universe.World; \n"
-					+ "import scala.collection.JavaConverters._;\n"
-					+ "class "+entName+" extends BatEntity { ";
-			
-			scalaFile.setCorrection(header+scalaFile.getCorrection()+" }");
-			scalaFile.setTemplate  (header+scalaFile.getTemplate()  +" }");
-		}
-		
+				
 		computeAnswer();
 		setSetup(true);
 	}
@@ -114,8 +102,6 @@ public abstract class ExerciseTemplating
 	protected void templateScala(String entName, String[] types, String initialCode, String correction) {
 		if (isSetup())
 			throw new RuntimeException("The exercise "+getName()+" is already setup, too late to add a programming language template.");
-		if (this.getProgLanguages().contains(Game.SCALA))
-			throw new RuntimeException("The exercise "+getName()+" has two Scala templates. Please fix this bug.");
 		
 		StringBuffer skeleton = new StringBuffer(" val res = ");
 		skeleton.append(entName);
@@ -146,9 +132,6 @@ public abstract class ExerciseTemplating
 		skeleton.append("  case e:java.lang.ClassCastException => t.setResult(res)\n"); // primitive types cannot be converted to java, but I don't care (and cannot test whether res is a primitive type)
 		skeleton.append("}\n");
 		
-		newSource(Game.SCALA, entName, initialCode, "\n   override def run(t: BatTest) {\n"+skeleton+"\n   }\n$body",14,
-				                                    "\n   override def run(t: BatTest) {\n"+skeleton+"\n   }\n"+initialCode+correction);
-		addProgLanguage(Game.SCALA);
 	}
 	public boolean isSetup() {
 		return isSetup;
Index: b/src/plm/core/ui/editor/MissionEditor.java
===================================================================
--- a/src/plm/core/ui/editor/MissionEditor.java
+++ b/src/plm/core/ui/editor/MissionEditor.java
@@ -110,7 +110,6 @@ public class MissionEditor extends JFram
 		selectorAll.setSelected(true);
 		final JCheckBox selectorC = new JCheckBox("C");
 		final JCheckBox selectorJava = new JCheckBox("Java");
-		final JCheckBox selectorScala = new JCheckBox("Scala");
 		final JCheckBox selectorPython = new JCheckBox("Python");
 
 		final ItemListener il = new ItemListener() {
@@ -129,9 +128,6 @@ public class MissionEditor extends JFram
 					if(selectorJava.isSelected()){
 						l.add(Game.JAVA);
 					}
-					if(selectorScala.isSelected()){
-						l.add(Game.SCALA);
-					}
 					if(selectorPython.isSelected()){
 						l.add(Game.PYTHON);
 					}
@@ -162,7 +158,6 @@ public class MissionEditor extends JFram
 		selectorAll.addItemListener(il);
 		selectorC.addItemListener(il);
 		selectorJava.addItemListener(il);
-		selectorScala.addItemListener(il);
 		selectorPython.addItemListener(il);
 
 		editor = new JEditorPane();
@@ -183,7 +178,6 @@ public class MissionEditor extends JFram
 		box.add(selectorAll);
 		box.add(selectorC);
 		box.add(selectorJava);
-		box.add(selectorScala);
 		box.add(selectorPython);
 
 		rightDisplay.add(box, BorderLayout.NORTH);
Index: b/src/plm/core/ui/JavaEditorPanel.java
===================================================================
--- a/src/plm/core/ui/JavaEditorPanel.java
+++ b/src/plm/core/ui/JavaEditorPanel.java
@@ -31,8 +31,6 @@ public class JavaEditorPanel extends RTe
             codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
         } else if (lang.equals(Game.PYTHON)) {
             codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PYTHON);
-        } else if (lang.equals(Game.SCALA)) {
-            codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SCALA);
         } else if (lang.equals(Game.C)) {
             codeEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_C);
         } else {
Index: b/src/plm/universe/bat/BatExercise.java
===================================================================
--- a/src/plm/universe/bat/BatExercise.java
+++ b/src/plm/universe/bat/BatExercise.java
@@ -98,7 +98,7 @@ public abstract class BatExercise extend
 		}
 
 		for (ProgrammingLanguage pl : getProgLanguages()) {
-			if (!pl.equals(Game.JAVA) && !pl.equals(Game.SCALA)) 
+			if (!pl.equals(Game.JAVA))
 				worlds.get(0).getEntity(0).setScript(pl, corrections.get(pl));
 		}
 		
Index: b/src/plm/test/simple/test/AllSimpleExerciseTests.java
===================================================================
--- a/src/plm/test/simple/test/AllSimpleExerciseTests.java
+++ b/src/plm/test/simple/test/AllSimpleExerciseTests.java
@@ -5,7 +5,7 @@ import org.junit.runners.Suite;
 import org.junit.runners.Suite.SuiteClasses;
 
 @RunWith(Suite.class)
-@SuiteClasses({ JavaSimpleExerciseTest.class, ScalaSimpleExerciseTest.class, PythonSimpleExerciseTest.class })
+@SuiteClasses({ JavaSimpleExerciseTest.class, PythonSimpleExerciseTest.class })
 public class AllSimpleExerciseTests {
 
 }
