use eclisp::{Lisp, LispClass, LispError, lisp_impl};
struct Transform {
x: f32,
y: f32,
}
#[derive(LispClass)]
#[lisp(name = "player", impl)]
struct Player {
#[lisp]
health: i32,
#[lisp(name = "movement-speed")]
speed: f32,
transform: Transform,
}
#[lisp_impl]
impl Player {
fn is_alive(&self) -> bool {
self.health > 0
}
fn max_health() -> i32 {
100
}
fn position_x(&self) -> f32 {
self.transform.x
}
fn position_y(&self) -> f32 {
self.transform.y
}
fn move_by(&mut self, dx: f32, dy: f32) {
self.transform.x += dx * self.speed;
self.transform.y += dy * self.speed;
}
}
#[lisp_impl(name = "player_combat")]
impl Player {
fn damage(&mut self, amount: i32) {
self.health -= amount;
}
}
fn main() -> Result<(), LispError> {
let lisp = Lisp::new()?;
lisp.enter(|ctx| {
ctx.defclass(Player::class())?;
ctx.defimpl(player_combat::methods())?;
let mut player = Player {
health: 100,
speed: 2.0,
transform: Transform { x: 1.0, y: 2.0 },
};
ctx.with(&mut player, |obj| {
let damage = ctx.int(25)?;
ctx.call("player-damage", &[obj, &damage])?;
let dx = ctx.float(5.0)?;
let dy = ctx.float(10.0)?;
ctx.call("player-move-by", &[obj, &dx, &dy])?;
let alive = ctx.call("player-is-alive", &[obj])?;
assert!(alive.try_as_bool()?);
let x = ctx.call("player-position-x", &[obj])?;
let y = ctx.call("player-position-y", &[obj])?;
assert!((x.try_as_f64()? - 11.0).abs() < 0.001);
assert!((y.try_as_f64()? - 22.0).abs() < 0.001);
Ok(())
})?;
let maximum = ctx.eval("(player-max-health)")?;
assert_eq!(maximum.try_as_i64()?, 100);
assert_eq!(player.health, 75);
assert_eq!(player.transform.x, 11.0);
assert_eq!(player.transform.y, 22.0);
println!("Health: {}", player.health);
println!("Position: ({}, {})", player.transform.x, player.transform.y);
println!("Maximum health: {}", maximum.try_as_i64()?);
Ok::<(), LispError>(())
})
}