## DEV Community

Steve Layton

Posted on • Updated on

# ATLG Rogue

## Decisions

Welcome back to another post in my rogue-ish Golang series. This week is going to be a very short post which doesn't cover much of the "game" itself. It's more a bit of a brain dump as I'm trying to decide on how I want to tackle adding creatures to the game.

There are a bunch of ways to do this. I'm trying to figure out what would be most appropriate for this and not complicate the code. We don't need any real display code since we'll just write our tests out to the console. We'll need to iterate on this throughout the next several weeks until we arrive at what we're looking for. And now...

## Code Walkthrough

We are keeping everything very basic for this code we're not going to include `tcell` or anything other than a die roller.

``````package main

import (
"fmt"
"math/rand"
"time"

"github.com/shindakun/die"
)
``````

One of the things we want to be able to do is a loop through our entire set of actors. So, we have an `Actors` struct which is a slice of the `Actor` struct. `Actor` is going to hold our basic "creature" information. That is the position (x,y), what floor they are on, and the `Creature` interface.

``````type Actors struct {
Actors []Actor
}

type Actor struct {
X        int
Y        int
Floor    int
Creature Creature
}
``````

Now we can create a simple method to "create" actors. We call `newActor()` and pass in where we want the actor to start on our stage and which floor. Our creature is also created and given "life" in this step. We'll see that a bit later on though...

``````func newActor(x, y, f int, c Creature) Actor {
return Actor{
X:        x,
Y:        y,
Floor:    f,
Creature: c,
}
}
``````

The creature interface declares all the methods a creature contains. We're trying it this way so each creature can have its own set of functions. We could move the methods on to `Actor` if this doesn't work. Which it may not. This way leads to a bit of code duplication since we're rewriting the same methods for each creature type.

``````type Creature interface {
GetRune() rune
GetHealth() int
GetDescription() string
TakeDamage(int)
}
``````

Here we have the majestic `pig` struct! I've already added JSON tags since I can imagine us loading basic creature data from disk. Currently, we have a rune (`p`), health (`10`), and a description (`I'm a pig!`). Not too exciting but it should work for now.

``````type Pig struct {
R           rune   `json:"r,omitempty"`
Health      int    `json:"health,omitempty"`
Description string `json:"description,omitempty"`
}
``````

To complete our pig "creature" we need to implement the parts of our `Creature` interface. The code is pretty descriptive so we won't touch on it too much.

``````func (p *Pig) GetRune() rune {
return p.R
}

func (p *Pig) GetHealth() int {
return p.Health
}

func (p *Pig) GetDescription() string {
return p.Description
}
func (p *Pig) TakeDamage(i int) {
p.Health = p.Health - i
}
``````

We need to be thinking about our actors moving around the world. So, I've created a basic `Move()` method which will allow our "pig" to move about. To do this we roll a four-sided die and move our pig based on the roll. 1 for North, 2 for East, 3 for South, 4 for West. We could update this at some point to allow for eight-way movement but for simplicity, we'll keep it at four for now.

Again, the code is pretty self-explanatory so we'll keep it brief. We roll for our direction and update the actor's position based on the results.

``````func (a *Actor) Move(floor int) {
if floor == a.Floor {
/*
1
4+2
3
*/
rand.Seed(time.Now().UTC().UnixNano())
var xx, yy int
d, err := die.Roll("1d4")
if err != nil {
panic("die roll")
}
switch d {
case 1:
xx = -1
case 2:
yy = 1
case 3:
xx = 1
case 4:
yy = -1
}
a.X = a.X + xx
a.Y = a.Y + yy
}
}
``````

We come now to the `main()` of our test. We will create our `a` "Actors".

``````func main() {
a := &Actors{}
``````

Then take `a.Actors` and start appending "new actors" to it. We create the new actor and setup the creature all in one go. Then we just print some stuff to the screen to test.

``````  a.Actors = append(a.Actors, newActor(1, 1, 1, &Pig{'p', 10, "From the realm of Paradox... the Pig."}))
a.Actors = append(a.Actors, newActor(2, 2, 1, &Pig{'p', 10, "Oink."}))

fmt.Printf("%#v\n\n", a)

fmt.Printf("%#v\n\n", a.Actors[0])

fmt.Printf("%#v\n\n", string(a.Actors[0].Creature.GetRune()))

fmt.Printf("%#v\n\n", a.Actors[0].Creature.GetHealth())

a.Actors[0].Creature.TakeDamage(5)

fmt.Printf("%#v\n\n", a.Actors[0].Creature.GetHealth())

fmt.Printf("%#v\n\n", a.Actors[1].Creature.GetDescription())

for i := range a.Actors {
a.Actors[i].Move(1)
}

fmt.Printf("%#v\n\n", a.Actors)
}
``````

## Wrapping Up

Seems to work alright, which is nice. If I have some time in the next day or so I'll try and work this into our code from last week to see how it goes.

You can find the code for this and most of the other Attempting to Learn Go posts in the repo on GitHub.

# Attempting to Learn Go

Here you can find the code I've been writing for my Attempting to Learn Go posts that I've been writing and posting over on Dev.to.