Golangの勉強がてら、Console上で動く簡易なゲームを作った

## 経緯
**ある雨の日**
`(^.^)：「Go？あーPokemon GOはもうやってないんだよなー。」`
`(?_?)：「え？Pokemon GOじゃないって？Golang？！」`
`('Д')：「なにそれ？おいしいの？」`
`(=_=)：「？！それ使ってXXX作らなくちゃいけないの？」`
`(*_*)：「まずは勉強しなくちゃ…」`

## 作ったもの
Console上で動くバトルアプリ？ゲーム？を作りました（学習がてら）。
（当時ヒーローアカデミアにはまってた）
ヒーローのSkillを上手いこと定義すれば、二人のHeroがいい感じの勝負をします。
定義のポイントとしては、speedを高く設定すると攻撃を避けやすくなります。
![2018-12-04_22h01_02_Trim.gif](https://qiita-image-store.s3.amazonaws.com/0/184925/0b989722-890b-e420-b8a8-b14c1accacd1.gif)

## 設定ファイルを用いないver
https://play.golang.org/p/nkVi7stskxf

## 設定ファイルを用いたver
HeroBattle
 　┣ HeroConfig.toml
 　┗ main.go

```HeroConfig.toml
# 【制約】3値が全て0以上かつ、power + speed + hp　が100を超えてはいけない
[hero1]
name  = "パワー系"
power = 50
speed = 15
hp    = 35
[hero2]
name  = "スピード系"
power = 15
speed = 50
hp    = 35
```

```main.go
package main

import (
	"fmt"
	"github.com/BurntSushi/toml"
	"github.com/shiena/ansicolor"
	"math"
	"math/rand"
	"os"
	"time"
)

//ヒーロー（インターフェース）
type Hero interface {
	Attack() int
	Defense(int) int
}

//能力（構造体）
type HeroConfig struct {
	Hero1 Skill
	Hero2 Skill
}

type Skill struct {
	Name  string
	Power int
	Speed int
	Hp    int
}

//攻撃（メソッド）・・・パワーで攻撃力が決定する
func (u *Skill) Attack() int {
	rand.Seed(time.Now().UnixNano())

	if 0 == rand.Intn(10) {
		fmt.Printf("クリティカル！\r\n\r\n")
		time.Sleep(3000 * time.Millisecond)
		fmt.Printf("（＊｀Д´）＝Э）TДT●）\r\n\r\n")
		return int(math.Sqrt(float64(u.Power))) * 2
	} else {
		return int(math.Sqrt(float64(u.Power)))
	}
}

//回避・ダメージ（メソッド）・・・Speedが速ければ、攻撃を回避しやすい
func (u *Skill) Defense(damage int) int {
	rand.Seed(time.Now().UnixNano())
	if u.Speed > rand.Intn(100) {
		fmt.Printf("回避成功\r\n\r\n")
		return u.Hp //回避成功
	} else {
		fmt.Printf("%dのダメージ\r\n\r\n", damage)
		u.Hp = u.Hp - damage
		return u.Hp //回避失敗
	}
}

//バトル（関数）
func Battle(hero1_info *Skill, hero2_info *Skill) {
	at := hero1_info
	df := hero2_info
	var AT Hero = hero1_info
	var DF Hero = hero2_info
	turn := 1
	for {
		fmt.Printf("%dラウンド-------------------------------\r\n", turn)
		fmt.Printf("【HP:%d】%s VS 【HP:%d】%s\r\n\r\n", at.Hp, at.Name, df.Hp, df.Name)
		fmt.Printf("%sの攻撃\r\n\r\n", at.Name)
		if DF.Defense(AT.Attack()) <= 0 {
			for i := 0; i < 5; i++ {
				fmt.Println("　　・")
				time.Sleep(500 * time.Millisecond)
			}
			fmt.Printf("【HP:%d】%sは力尽きた・・・。【HP:%d】%sの勝利！！！\r\n\r\n", df.Hp, df.Name, at.Hp, at.Name)
			return
		}
		time.Sleep(1000 * time.Millisecond)
		//攻守交換
		temp := at
		at = df
		df = temp
		TEMP := AT
		AT = DF
		DF = TEMP
		turn++
	}
}

//能力の上限チェック（関数） 第三引数のlimitよりもPower+Speed+Hpが上回ってはいけない
func SkillCheck(hero1 *Skill, hero2 *Skill, limit int) bool {
	check1 := hero1.Power + hero1.Speed + hero1.Hp
	check2 := hero2.Power + hero2.Speed + hero2.Hp
	fmt.Printf("limit:%d\r\n", limit)
	fmt.Printf("〇先行：%s\r\nPower:%d\r\nSpeed:%d\r\nHp   :%d\r\nSum  :%d\r\n\r\n", hero1.Name, hero1.Power, hero1.Speed, hero1.Hp, check1)
	fmt.Printf("△後攻：%s\r\nPower:%d\r\nSpeed:%d\r\nHp   :%d\r\nSum  :%d\r\n\r\n", hero2.Name, hero2.Power, hero2.Speed, hero2.Hp, check2)
	if check1 <= limit && check2 <= limit && hero1.Power > 0 && hero1.Speed > 0 && hero1.Hp > 0 && hero2.Power > 0 && hero2.Speed > 0 && hero2.Hp > 0 {
		return true
	} else {
		return false
	}
}

func main() {
	w := ansicolor.NewAnsiColorWriter(os.Stdout)
	// tomlファイルから情報を読み取る
	var hero HeroConfig
	_, err := toml.DecodeFile("HeroConfig.toml", &hero)
	if err != nil {
		panic(err)
	}
	// バトル開始　能力の上限値は100 能力の上限を超えていればバトルは行われない。
	if SkillCheck(&hero.Hero1, &hero.Hero2, 100) == true {
		Battle(&hero.Hero1, &hero.Hero2)
	} else {
		fmt.Printf("バトル開始不可能")
	}
	fmt.Fprintf(w, "\r\n%s SUCCESS!!!%s", "\x1b[33m\x1b[1m", "\x1b[22m\x1b[0m")
}

```