Skip to content

Instantly share code, notes, and snippets.

@cooper6581
Created September 16, 2014 00:43
Show Gist options
  • Save cooper6581/07a8015438f10231029a to your computer and use it in GitHub Desktop.
Save cooper6581/07a8015438f10231029a to your computer and use it in GitHub Desktop.
Daily #179 - Hard
package main
import (
. "code.google.com/p/goncurses"
"fmt"
"log"
"math"
"math/rand"
"time"
)
const (
floor = iota
wall = iota
loot = iota
torch = iota
barrier_size = 3
number_of_loots = 60
number_of_torches = 7
)
type Player struct {
x int
y int
m_points int
loot int
torch_mode bool
torch_power float64
}
func init_curses() *Window {
stdscr, err := Init()
if err != nil {
log.Fatal("init", err)
}
err = StartColor()
if err != nil {
log.Fatal("init", err)
}
err = InitPair(1, C_WHITE, C_BLACK)
if err != nil {
log.Fatal("init", err)
}
err = InitPair(2, C_GREEN, C_BLACK)
if err != nil {
log.Fatal("init", err)
}
err = InitPair(3, C_YELLOW, C_BLACK)
if err != nil {
log.Fatal("init", err)
}
err = InitPair(4, C_RED, C_BLACK)
if err != nil {
log.Fatal("init", err)
}
err = InitPair(5, C_BLUE, C_BLACK)
if err != nil {
log.Fatal("init", err)
}
Echo(false)
Cursor(0)
CBreak(true)
stdscr.Keypad(true)
return stdscr
}
func new_player(size int, level []byte) Player {
rand_x := rand.Intn(size)
rand_y := rand.Intn(size)
for level[rand_y*size+rand_x] != floor {
rand_x = rand.Intn(size)
rand_y = rand.Intn(size)
}
return Player{x: rand_x, y: rand_y, m_points: 100,
loot: 0, torch_mode: true, torch_power: 2.4}
}
func generate_stuff(size int, level []byte, thing byte, number_of_things int) {
// Generate things
things_generated := 0
for things_generated < number_of_things {
x := rand.Intn(size)
y := rand.Intn(size)
if level[y*size+x] != floor {
continue
}
level[y*size+x] = thing
things_generated++
}
}
func generate_level(size int) []byte {
rand.Seed(time.Now().UnixNano())
level := make([]byte, size*size)
// Walls
for y := 0; y < size; y++ {
for x := 0; x < size; x++ {
if y == 0 || y == size-1 || x == 0 || x == size-1 {
level[y*size+x] = wall
} else {
level[y*size+x] = floor
}
}
}
// Barriers
barriers_generated := 0
for barriers_generated < 5 {
barrier_type := rand.Intn(2)
// horizontal
if barrier_type == 0 {
rand_x := rand.Intn(size-barrier_size) + 1
rand_y := rand.Intn(size-1) + 1
for x := rand_x; x < rand_x+barrier_size; x++ {
level[rand_y*size+x] = wall
}
// vertical
} else {
rand_x := rand.Intn(size-1) + 1
rand_y := rand.Intn(size-barrier_size) + 1
for y := rand_y; y < rand_y+barrier_size; y++ {
level[y*size+rand_x] = wall
}
}
barriers_generated++
}
// generate loot
generate_stuff(size, level, loot, number_of_loots)
// generate torches
generate_stuff(size, level, torch, number_of_torches)
return level
}
func draw(level []byte, size int, stdscr *Window, player *Player) {
stdscr.Clear()
for y := 0; y < size; y++ {
for x := 0; x < size; x++ {
if distance(player, x, y) < player.torch_power || !player.torch_mode {
switch level[y*size+x] {
case wall:
stdscr.MoveAddChar(y, x, '#'|ColorPair(1))
case floor:
stdscr.MoveAddChar(y, x, '.'|ColorPair(3))
case loot:
stdscr.MoveAddChar(y, x, '$'|ColorPair(2))
case torch:
stdscr.MoveAddChar(y, x, 'T'|ColorPair(4))
}
} else {
stdscr.MoveAddChar(y, x, ' '|ColorPair(1))
}
}
}
stdscr.MoveAddChar(player.y, player.x, '@'|A_BOLD|ColorPair(5))
stdscr.MovePrintf(size+1, 0, "Movement Points: %d Loot: %d",
player.m_points, player.loot)
stdscr.Refresh()
}
func distance(player *Player, x, y int) float64 {
return math.Sqrt(
math.Pow(float64(player.x-x), 2) +
math.Pow(float64(player.y-y), 2))
}
func get_input(stdscr *Window, player *Player, level []byte, size int) bool {
ch := stdscr.GetChar()
// store old player location
old_player := *player
// get input
switch Key(ch) {
case 'q', 'Q':
return false
case 't', 'T':
player.torch_mode = !player.torch_mode
case KEY_LEFT:
player.x--
case KEY_RIGHT:
player.x++
case KEY_DOWN:
player.y++
case KEY_UP:
player.y--
}
// hit detection for walls
if level[player.y*size+player.x] == wall {
*player = old_player
} else {
if distance(player, old_player.x, old_player.y) > 0 {
player.m_points--
}
}
// loots
if level[player.y*size+player.x] == loot {
level[player.y*size+player.x] = floor
player.loot++
}
// torch
if level[player.y*size+player.x] == torch {
level[player.y*size+player.x] = floor
player.torch_power++
}
if player.m_points == 0 {
return false
}
return true
}
func main() {
size := 20
stdscr := init_curses()
level := generate_level(size)
player := new_player(size, level)
running := true
for running {
draw(level, size, stdscr, &player)
if !get_input(stdscr, &player, level, size) {
break
}
}
End()
fmt.Println("Game Over! Score:", player.loot)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment