Created
September 16, 2014 00:43
-
-
Save cooper6581/07a8015438f10231029a to your computer and use it in GitHub Desktop.
Daily #179 - Hard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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