3 people following this project (follow)

Project Description
The Casanova language is a programming language designed around games. The compiler generates highly optimized .Net libraries from succint, declarative descriptions. The generated library uses spatial optimizations, multithreading and more, and can be used with XNA or other libs.

Casanova is a research project, and as such there are various Papers written about it.

Casanova is strongly tied with F#, from which it borrows heavily in terms of syntax. Casanova also features Haskell style list-comprehensions, which are then heavily optimized with physical query optimizations (such as oc-, quad- or kd- trees). Casanova programs are also optimized with multithreading.

Rewriting a game in Casanova may yield important advantages, such as:
  • faster runtime on both PC and Xbox; check the source code for an example on how remaking Spacewar can give up to 50x the original performance of the game
  • smaller sources; again, check the samples to see how the 1000+ lines of code of Spacewar become less than 350 in Casanova
  • greater expressive power: Casanova integrates coroutines, so writing a state machine has never been easier
  • cleaner interaction between entities: define your state and how it updates easily and intuitively


Let us show how we would build a very simple game where asteroids fall down from the screen and are removed when they reach the bottom of the screen. We start by defining the state and its rules:

type Asteroid =
  {
    Y     : Rule float
          :: fun (self,y,dt) -> y + dt * self.VelY
        
    VelY  : float        
    X     : float
  }

type GameState =
  {
    Asteroids           
        : Rule(Table Asteroid)
        :: fun asteroids -> [a | a <- asteroids && a.Y > 0]
  	    
    DestroyedAsteroids	
        : Rule<int>
        :: fun (state,destroyed_asteroids) -> destroyed_asteroids + count([a | a <- !state.Asteroids && a.Y <= 0])
  }


In a field declaration, the : operator means "has type", while the :: operator specifies the charateristic function associated with a rule.

In the state definition above we can see that the state is comprised by a set of asteroids which are removed when they reach the bottom. Removing these asteroids increments a counter, which is essentially the "score" of our pseudo-game. Each asteroid moves in the direction of its velocity.

The initial state is then provided:
let state0 =
  {
    Asteroids               = []
    DestroyedAsteroids      = 0
  }


Rules specify those computational aspects of the game which never change. Rules require the same computation at every tick of the game. Certain computations in a game must run during more than one tick; for example, long-running computations that involve timers and waiting for certain conditions of the game state to be met. These are called behaviors, and are implemented with coroutines. Behaviors in Casanova are imperative procedures which may invoke the \texttt{yield} operation. Yielding inside a behavior suspends it until the next tick of the game. Behaviors may freely access the state for writing, that is behaviors are less constrained than rules but for this reason they also support less optimizations. The only requirement that Casanova enforces in behaviors is that they must never repeat without yielding; behaviors like:

repeat
  {
    x := !x + 1
  }


(where := is the assignment operator and {!} is the lookup operator) generate a compile error.

When the main behavior of a game terminates, the game quits.

The main behavior of our game spawns asteroids every 1-3 seconds until the number of destroyed asteroids reaches 100. The main behavior of our game is defined last, after the auxiliary function \texttt{wait}:

let main state =
  let random = mk_random()
  let rec wait interval =
    {
      let! t0 = time
      do! yield
      let! t = time
      let dt = t - t0
      if dt > interval then
        return ()
      else
        do! wait (interval - dt)
    }  
  let rec behavior() =
    {
      do! wait (random.Next(1,3))
      do! state.Asteroids.Add
      	  {
      	    X     = random.Next(-1,+1)
      	    Y     = 1
      	    VelY  = random.Next(-0.1,-0.2)
      	  }
      if !state.DestroyedAsteroids < 100 then
        do! behavior()
      else
        return ()
    }
  in behavior()





The structure of the finished compiler will be the following:
  • a parser parses Casanova programs UNDER CONSTRUCTION
  • an F# quotation is generated UNDER CONSTRUCTION
  • the F# quotation is optimized UNDER CONSTRUCTION
  • the resulting program is compiled with the F# compiler UNDER CONSTRUCTION

Last edited Jan 14 at 7:58 AM by giuseppemag, version 4