|
|
@ -34,13 +34,15 @@ type Position struct { |
|
|
|
|
|
|
|
|
|
|
|
type Enemy struct { |
|
|
|
type Enemy struct { |
|
|
|
hp int |
|
|
|
hp int |
|
|
|
|
|
|
|
pos Position |
|
|
|
|
|
|
|
damage int |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type Game struct { |
|
|
|
type Game struct { |
|
|
|
screen tcell.Screen |
|
|
|
screen tcell.Screen |
|
|
|
level Map |
|
|
|
level Map |
|
|
|
paths Paths |
|
|
|
paths Paths |
|
|
|
player Position |
|
|
|
player Enemy |
|
|
|
status string |
|
|
|
status string |
|
|
|
width int |
|
|
|
width int |
|
|
|
height int |
|
|
|
height int |
|
|
@ -104,7 +106,7 @@ func (game *Game) Render() { |
|
|
|
game.DrawPaths() |
|
|
|
game.DrawPaths() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
game.DrawEntity('@', game.player, tcell.ColorYellow) |
|
|
|
game.DrawEntity('@', game.player.pos, tcell.ColorYellow) |
|
|
|
|
|
|
|
|
|
|
|
for pos, _ := range game.enemies { |
|
|
|
for pos, _ := range game.enemies { |
|
|
|
game.DrawEntity('G', pos, tcell.ColorRed) |
|
|
|
game.DrawEntity('G', pos, tcell.ColorRed) |
|
|
@ -126,7 +128,7 @@ func (game *Game) Exit() { |
|
|
|
func (game *Game) Occupied(x int, y int) bool { |
|
|
|
func (game *Game) Occupied(x int, y int) bool { |
|
|
|
pos := Position{x, y} |
|
|
|
pos := Position{x, y} |
|
|
|
_, is_enemy := game.enemies[pos] |
|
|
|
_, is_enemy := game.enemies[pos] |
|
|
|
is_player := pos == game.player |
|
|
|
is_player := pos == game.player.pos |
|
|
|
|
|
|
|
|
|
|
|
// Inbounds comes first to prevent accessing level with bad x,y
|
|
|
|
// Inbounds comes first to prevent accessing level with bad x,y
|
|
|
|
return !game.Inbounds(pos, 1) || |
|
|
|
return !game.Inbounds(pos, 1) || |
|
|
@ -135,7 +137,7 @@ func (game *Game) Occupied(x int, y int) bool { |
|
|
|
is_player |
|
|
|
is_player |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (game *Game) Death() { |
|
|
|
func (game *Game) EnemyDeath() { |
|
|
|
is_dead := make([]Position, 0, len(game.enemies)) |
|
|
|
is_dead := make([]Position, 0, len(game.enemies)) |
|
|
|
|
|
|
|
|
|
|
|
for pos, enemy := range game.enemies { |
|
|
|
for pos, enemy := range game.enemies { |
|
|
@ -149,28 +151,37 @@ func (game *Game) Death() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (game *Game) Attack(target Position) { |
|
|
|
func (game *Game) ApplyDamage(attacker *Enemy, defender *Enemy) { |
|
|
|
enemy, hit_enemy := game.enemies[target] |
|
|
|
damage := rand.Int() % attacker.damage |
|
|
|
|
|
|
|
defender.hp -= damage |
|
|
|
if hit_enemy { |
|
|
|
|
|
|
|
damage := rand.Int() % 10 |
|
|
|
|
|
|
|
enemy.hp -= damage |
|
|
|
|
|
|
|
if damage == 0 { |
|
|
|
if damage == 0 { |
|
|
|
game.Status("YOU MISSED!") |
|
|
|
game.Status("MISSED!") |
|
|
|
} else if enemy.hp > 0 { |
|
|
|
} else if defender.hp > 0 { |
|
|
|
game.Status(fmt.Sprintf("HIT %d damage", damage)) |
|
|
|
game.Status(fmt.Sprintf("HIT %d damage", damage)) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
game.Status("ENEMY DEAD!") |
|
|
|
game.Status("DEAD!") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (game *Game) Attack(target Position) { |
|
|
|
|
|
|
|
enemy, hit_enemy := game.enemies[target] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if hit_enemy { |
|
|
|
|
|
|
|
game.ApplyDamage(&game.player, enemy) |
|
|
|
|
|
|
|
game.ApplyDamage(enemy, &game.player) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (game *Game) MovePlayer(x_delta int, y_delta int) { |
|
|
|
func (game *Game) MovePlayer(x_delta int, y_delta int) { |
|
|
|
target := Position{game.player.x + x_delta, game.player.y + y_delta} |
|
|
|
target := Position{ |
|
|
|
|
|
|
|
game.player.pos.x + x_delta, |
|
|
|
|
|
|
|
game.player.pos.y + y_delta, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if game.Occupied(target.x, target.y) { |
|
|
|
if game.Occupied(target.x, target.y) { |
|
|
|
game.Attack(target) |
|
|
|
game.Attack(target) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
game.player = target |
|
|
|
game.player.pos = target |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -209,11 +220,19 @@ func (game *Game) HandleEvents() bool { |
|
|
|
return true |
|
|
|
return true |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func MakeGame(width int, height int) (*Game) { |
|
|
|
func (game *Game) InitScreen() { |
|
|
|
var game Game |
|
|
|
encoding.Register() |
|
|
|
|
|
|
|
|
|
|
|
var err error |
|
|
|
var err error |
|
|
|
|
|
|
|
game.screen, err = tcell.NewScreen() |
|
|
|
|
|
|
|
if err != nil { log.Fatal(err) } |
|
|
|
|
|
|
|
|
|
|
|
encoding.Register() |
|
|
|
err = game.screen.Init() |
|
|
|
|
|
|
|
if err != nil { log.Fatal(err) } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func MakeGame(width int, height int) (*Game) { |
|
|
|
|
|
|
|
var game Game |
|
|
|
|
|
|
|
|
|
|
|
game.width = width |
|
|
|
game.width = width |
|
|
|
game.height = height |
|
|
|
game.height = height |
|
|
@ -222,15 +241,7 @@ func MakeGame(width int, height int) (*Game) { |
|
|
|
game.level = make(Map, height, height) |
|
|
|
game.level = make(Map, height, height) |
|
|
|
game.paths = make(Paths, height, height) |
|
|
|
game.paths = make(Paths, height, height) |
|
|
|
|
|
|
|
|
|
|
|
if RENDER { |
|
|
|
game.player = Enemy{20, Position{1,1}, 4} |
|
|
|
game.screen, err = tcell.NewScreen() |
|
|
|
|
|
|
|
if err != nil { log.Fatal(err) } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = game.screen.Init() |
|
|
|
|
|
|
|
if err != nil { log.Fatal(err) } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
game.player = Position{1,1} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return &game |
|
|
|
return &game |
|
|
|
} |
|
|
|
} |
|
|
@ -401,7 +412,7 @@ func (game *Game) PathAddNeighbors(neighbors []Position, closed Map, near Positi |
|
|
|
func (game *Game) PathEnemies() { |
|
|
|
func (game *Game) PathEnemies() { |
|
|
|
in_grid := make([][]int, game.height, game.height) |
|
|
|
in_grid := make([][]int, game.height, game.height) |
|
|
|
game.FillPaths(in_grid, 1) |
|
|
|
game.FillPaths(in_grid, 1) |
|
|
|
in_grid[game.player.y][game.player.x] = 0 |
|
|
|
in_grid[game.player.pos.y][game.player.pos.x] = 0 |
|
|
|
|
|
|
|
|
|
|
|
game.FillPaths(game.paths, PATH_LIMIT) |
|
|
|
game.FillPaths(game.paths, PATH_LIMIT) |
|
|
|
closed := game.CloneMap() |
|
|
|
closed := game.CloneMap() |
|
|
@ -496,27 +507,42 @@ func (game *Game) MakeMap() []Position { |
|
|
|
func (game *Game) PlaceEnemies(places []Position) { |
|
|
|
func (game *Game) PlaceEnemies(places []Position) { |
|
|
|
for _, pos := range places { |
|
|
|
for _, pos := range places { |
|
|
|
if rand.Int() % 2 == 0 { |
|
|
|
if rand.Int() % 2 == 0 { |
|
|
|
game.enemies[pos] = &Enemy{10} |
|
|
|
game.enemies[pos] = &Enemy{10, pos, 4} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (game *Game) Restart() { |
|
|
|
|
|
|
|
game.Status("YOU DIED! Try again.") |
|
|
|
|
|
|
|
game.player.hp = 20 |
|
|
|
|
|
|
|
game.player.pos = Position{1,1} |
|
|
|
|
|
|
|
game.screen.Clear() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func main() { |
|
|
|
func main() { |
|
|
|
out, err := os.Create("debug.log") |
|
|
|
out, err := os.Create("debug.log") |
|
|
|
if err != nil { log.Fatal(err) } |
|
|
|
if err != nil { log.Fatal(err) } |
|
|
|
dbg = log.New(out, "", log.LstdFlags) |
|
|
|
dbg = log.New(out, "", log.LstdFlags) |
|
|
|
|
|
|
|
|
|
|
|
game := MakeGame(27, 17) |
|
|
|
game := MakeGame(27, 17) |
|
|
|
|
|
|
|
game.InitScreen() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for { |
|
|
|
dead_ends := game.MakeMap() |
|
|
|
dead_ends := game.MakeMap() |
|
|
|
game.PlaceEnemies(dead_ends) |
|
|
|
game.PlaceEnemies(dead_ends) |
|
|
|
game.Render() |
|
|
|
game.Render() |
|
|
|
|
|
|
|
|
|
|
|
for game.HandleEvents() { |
|
|
|
for game.HandleEvents() && game.player.hp > 0 { |
|
|
|
game.Death() |
|
|
|
game.EnemyDeath() |
|
|
|
game.PathEnemies() |
|
|
|
game.PathEnemies() |
|
|
|
game.EnemyMovement() |
|
|
|
game.EnemyMovement() |
|
|
|
game.Render() |
|
|
|
game.Render() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if game.player.hp <= 0 { |
|
|
|
|
|
|
|
game.Restart() |
|
|
|
|
|
|
|
} else { |
|
|
|
game.Exit() |
|
|
|
game.Exit() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|