Game
Here is a short program written in Ki.
import math
const LAVA_SPOT_COUNT: 6
const PLAYER_COUNT: 2
const ENEMY_COUNT: 4
const AMMO: 10
struct Size {
var width: uint(0)
var height: uint(0)
var depth: uint(0)
}
struct Point {
var x: uint(0)
var y: uint(0)
var z: uint(0)
static fn random(Point min, Point max) (*Point!) {
var point: *Point(
math.rand_uint_range(min.x, max.x)
math.rand_uint_range(min.y, max.y)
math.rand_uint_range(min.z, max.z)
)
return *point!
}
:eq fn(Point other) (bool) {
return self.x == other.x && self.y == other.y && self.z == other.z
}
fn randomize(Point min, Point max) {
self.x = math.rand_uint_range(min.x, max.x)
self.y = math.rand_uint_range(min.y, max.y)
self.z = math.rand_uint_range(min.z, max.z)
}
}
component MapInhabiter {
:requirements {
val position: Point
val map: &Map
}
get position (Point) {
return Point
}
set position (Point new_point) {
if (new_point.x >= self.map.size.width ||
new_point.y >= self.map.size.height ||
new_point.z >= self.map.size.depth) {
error({
"Position ${new_point.to_string()} outside bounds "
"${self.map.size.to_string()}."
})
}
self.position.x = new_point.x
self.position.y = new_point.y
self.position.z = new_point.z
}
set map (Map &new_map) {
self.map = new_map
}
pred is_in_lava {
for (lava_spot in self.map.lava_spots) {
if (self.position == lava_spot) {
return true
}
}
return false
}
}
struct Enemy {
val position: Point
:components {
MapInhabiter
}
static fn at_random_position(Point min, Point max) (*Enemy) {
val enemy: *Enemy(
position: Point.random(min, max)
)
return *enemy
}
}
struct Player {
var position: Point
var ammo: u8(0)
:components {
MapInhabiter
}
static fn at_random_position(Point min, Point max, uint ammo) (*Player!) {
var player: *Player(
position: Point.random(min, max),
ammo: ammo
)
return *player!
}
fn move() {
@overflow.limit {
self.position.x += 14
}
}
fn shoot() {
@overflow.limit {
self.ammo--
}
}
}
array LavaSpotArray<Point>
dynarray EnemyArray<*Enemy>
dynarray PlayerArray<*Player!>
struct Map {
val size: Size
val lava_spots: *LavaSpotArray
}
struct Game {
var map: Map
var players: PlayerArray
var enemies: EnemyArray
fn add_player(Player *p!) {
self.players.append(*p!)
}
fn add_enemy(Enemy *e) {
self.enemies.append(*e)
}
fn tick() {
with (self.players.create_deletion_list() as player_delist) {
for (i, player in self.players) {
player.move()
if (self.map.in_lava(player)) {
echo("Player ${i + 1} fell in the lava!")
player_delist.add(i)
continue
}
player.shoot()
with (self.enemies.create_deletion_list() as enemy_delist) {
for (j, enemy in self.enemies) {
if (enemy.position.x == player.position.x) {
echo("Player ${i + 1} shot enemy ${j + 1}!")
enemy_delist.add(j)
continue
}
}
}
}
}
}
}
fn main() {
val msize: Size(20, 1, 20)
val zero: Point()
val max: Point(msize.width - 1, msize.height - 1, msize.depth - 1)
var game: Game(
map: Map(
size: msize
lava_spots: *PointArray(count: LAVA_SPOT_COUNT)
)
}
for (&point! in lava_spots) {
point.randomize(zero, max)
}
loop (PLAYER_COUNT) {
game.add_player(*Player.at_random_position(zero, max, AMMO)!)
}
loop (ENEMY_COUNT) {
game.add_enemy(*Enemy.at_random_position(zero, max))
}
while ((game.players.length > 0) && (enemies.players.length > 0)) {
game.tick()
}
if (game.players.length <= 0) {
echo("All players died, enemies win :(")
}
else {
echo("All enemies died, players win :)")
}
}
# vi: set et sw=4 ts=4 tw=79: