can start a game

This commit is contained in:
stryan 2022-02-20 18:36:52 -05:00
parent 32e7fa3278
commit 6c356c9731
9 changed files with 219 additions and 67 deletions

View File

@ -47,7 +47,7 @@ func TestNewBoard(t *testing.T) {
func TestGetPiece(t *testing.T) {
b := NewBoard(4)
p := NewPiece(2, Red)
p := NewPieceFromInt(2, Red)
b.board[0][0].entity = p
np, err := b.GetPiece(9, 9)
if err == nil {
@ -68,7 +68,7 @@ func TestGetPiece(t *testing.T) {
func TestPlace(t *testing.T) {
b := NewBoard(4)
p := NewPiece(2, Red)
p := NewPieceFromInt(2, Red)
res, err := b.Place(8, 9, p)
if err == nil {
t.Errorf("able to place in invalid location")
@ -94,7 +94,7 @@ func TestPlace(t *testing.T) {
func TestRemove(t *testing.T) {
b := NewBoard(4)
p := NewPiece(2, Red)
p := NewPieceFromInt(2, Red)
res, err := b.Place(0, 0, p)
if err != nil {

51
colour_enumer.go Normal file
View File

@ -0,0 +1,51 @@
// Code generated by "enumer -type=Colour"; DO NOT EDIT.
//
package main
import (
"fmt"
)
const _ColourName = "RedBlueNoColour"
var _ColourIndex = [...]uint8{0, 3, 7, 15}
func (i Colour) String() string {
if i < 0 || i >= Colour(len(_ColourIndex)-1) {
return fmt.Sprintf("Colour(%d)", i)
}
return _ColourName[_ColourIndex[i]:_ColourIndex[i+1]]
}
var _ColourValues = []Colour{0, 1, 2}
var _ColourNameToValueMap = map[string]Colour{
_ColourName[0:3]: 0,
_ColourName[3:7]: 1,
_ColourName[7:15]: 2,
}
// ColourString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func ColourString(s string) (Colour, error) {
if val, ok := _ColourNameToValueMap[s]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Colour values", s)
}
// ColourValues returns all values of the enum
func ColourValues() []Colour {
return _ColourValues
}
// IsAColour returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Colour) IsAColour() bool {
for _, v := range _ColourValues {
if i == v {
return true
}
}
return false
}

View File

@ -8,7 +8,7 @@ import (
"strings"
)
var cmdRegxp = regexp.MustCompile("([a-zA-Z])([1-9])(x|-)([a-zA-Z])([1-9])")
var cmdRegxp = regexp.MustCompile("([a-zA-Z])([0-9])(x|-)([a-zA-Z])([0-9])")
var ranks = "ABCDEFHIJKLMNOPQRSTUVWXYZ"
//RawCommand is a game command, converted from algebraic notation

View File

@ -17,6 +17,7 @@ func TestNewRawCommand(t *testing.T) {
}{
{"A1xC3", true, 0, 1, 2, 3, "x"},
{"d7-d1", true, 3, 7, 3, 1, "-"},
{"c0-c1", true, 2, 0, 2, 1, "-"},
{"AA-k3", false, 0, 0, 0, 0, ""},
{"a1/b4", false, 0, 0, 0, 0, ""},
}

18
game.go
View File

@ -19,6 +19,7 @@ const (
)
//Colour reperensents player colour
//go:generate enumer -type=Colour
type Colour int
//Colour consts
@ -112,7 +113,7 @@ func (g *Game) Mutate(cmd *ParsedCommand) (bool, error) {
return false, errors.New("bad game state")
}
}
return true, nil
return res, nil
}
//SetupPiece adds a piece to the board during setup
@ -120,11 +121,14 @@ func (g *Game) SetupPiece(x, y int, p *Piece) (bool, error) {
if g.state != gameSetup {
return false, errors.New("Trying to setup piece when not in setup")
}
if p == nil {
return false, errors.New("Tried to setup a nil piece")
}
if !g.board.validatePoint(x, y) {
return false, errors.New("Invalid location")
}
if p.Owner != g.board.GetColor(x, y) {
return false, errors.New("Can't setup piece on enemy board")
return false, fmt.Errorf("Can't setup piece on enemy board: %v != %v", p.Owner, g.board.GetColor(x, y))
}
return g.board.Place(x, y, p)
}
@ -208,7 +212,7 @@ func (g *Game) strike(x, y, s, t int) (bool, error) {
//endPiece lost
g.board.Remove(s, t)
//scouts replace the piece that was destroyed
if startPiece.Rank == 1 {
if startPiece.Rank == Scout {
g.board.Remove(x, y)
g.board.Place(s, t, startPiece)
}
@ -228,11 +232,15 @@ func (g *Game) combat(atk, def *Piece) (int, error) {
}
//handle special cases first
//miner hitting bomb
if atk.Rank == 3 && def.Rank == 12 {
if atk.Rank == Miner && def.Rank == Bomb {
return 1, nil
}
//anyone else hitting bomb
if def.Rank == Bomb {
return -1, nil
}
//spy hitting marshal
if atk.Rank == 0 && def.Rank == 10 {
if atk.Rank == Spy && def.Rank == Marshal {
return 1, nil
}
//normal cases

View File

@ -1,29 +1,63 @@
package main
import "testing"
import (
"errors"
"fmt"
"testing"
)
func dummyMiniGame() *Game {
func dummyMiniGame() (*Game, error) {
g := &Game{
board: NewBoard(4),
state: gameSetup,
}
//Setup terrain
g.board.AddTerrain(1, 1, 1)
g.board.AddTerrain(2, 2, 1)
//Setup blue (5 pieces)
g.SetupPiece(0, 0, NewPiece(0, Blue))
g.SetupPiece(0, 1, NewPiece(1, Blue))
g.SetupPiece(0, 2, NewPiece(2, Blue))
g.SetupPiece(0, 3, NewPiece(3, Blue))
g.SetupPiece(1, 3, NewPiece(4, Blue))
//Setup red (5 pieces)
g.SetupPiece(3, 0, NewPiece(0, Red))
g.SetupPiece(3, 1, NewPiece(1, Red))
g.SetupPiece(3, 2, NewPiece(2, Red))
g.SetupPiece(3, 3, NewPiece(3, Red))
g.SetupPiece(2, 1, NewPiece(4, Red))
terrain := []struct {
x, y, t int
}{
{1, 1, 1},
{2, 2, 1},
}
for _, tt := range terrain {
res, err := g.board.AddTerrain(tt.x, tt.y, tt.t)
if err != nil {
return nil, err
}
if !res {
return nil, errors.New("Error creating terrain")
}
}
pieces := []struct {
x, y int
p *Piece
}{
{0, 0, NewPiece(Flag, Blue)},
{3, 0, NewPiece(Spy, Blue)},
{2, 0, NewPiece(Captain, Blue)},
{3, 1, NewPiece(Marshal, Blue)},
{0, 1, NewPiece(Bomb, Blue)},
return g
{1, 2, NewPiece(Flag, Red)},
{3, 2, NewPiece(Spy, Red)},
{2, 3, NewPiece(Captain, Red)},
{0, 2, NewPiece(Marshal, Red)},
{0, 3, NewPiece(Bomb, Red)},
}
for _, tt := range pieces {
res, err := g.SetupPiece(tt.x, tt.y, tt.p)
if err != nil {
return nil, fmt.Errorf("Piece %v,%v:%v", tt.x, tt.y, err)
}
if !res {
return nil, errors.New("error placing dummy piece")
}
}
_, err := g.SetupPiece(0, 0, NewPiece(Flag, Blue))
if err != nil {
return nil, err
}
return g, nil
}
func TestNewGame(t *testing.T) {
@ -38,8 +72,8 @@ func TestNewGame(t *testing.T) {
func TestSetupPiece(t *testing.T) {
g := NewGame()
p1 := NewPiece(0, Blue)
p2 := NewPiece(0, Red)
p1 := NewPieceFromInt(0, Blue)
p2 := NewPieceFromInt(0, Red)
res, err := g.SetupPiece(0, 0, p1)
if err == nil || res == true {
t.Errorf("Expected to fail setup piece but didn't")
@ -57,7 +91,7 @@ func TestSetupPiece(t *testing.T) {
if err == nil {
t.Error("expected to fail setting up piece in invalid spot")
}
res, err = g.SetupPiece(4, 0, p2)
res, err = g.SetupPiece(4, 5, p2)
if err != nil {
t.Fatal(err)
}
@ -75,3 +109,62 @@ func TestStart(t *testing.T) {
t.Fatal("expected game to start")
}
}
func TestMiniCreation(t *testing.T) {
g, err := dummyMiniGame()
if err != nil {
t.Fatalf("mini game not created: %v", err)
}
if g.state != gameSetup {
t.Fatal("mini game not in right state")
}
}
func TestMiniGame1(t *testing.T) {
g, err := dummyMiniGame()
if err != nil {
t.Fatal(err)
}
if !g.Start() {
t.Fatal("could not start mini game")
}
if g.state != gameTurnRed {
t.Error("game starting on wrong turn")
}
r := NewDummyPlayer(Red)
b := NewDummyPlayer(Blue)
var moves = []struct {
input string
player Player
res bool
}{
{"c3-b3", r, true},
{"c0-c1", b, true},
{"d2xd1", r, true},
{"c1-d1", b, true},
{"b3-c3", r, true},
{"d1xd2", b, true},
}
i := 0
for _, tt := range moves {
tname := fmt.Sprintf("%v input: %v", i, tt.input)
i++
t.Run(tname, func(t *testing.T) {
raw, err := NewRawCommand(tt.input)
if err != nil {
t.Fatalf("error creating RawCommand from %v:%v", tt.input, err)
}
parsed, err := g.Parse(tt.player, raw)
if err != nil {
t.Fatal(err)
}
res, err := g.Mutate(parsed)
if err != nil {
t.Error(err)
}
if tt.res != res {
t.Errorf("Expected command to be %v but was %v", tt.res, res)
}
})
}
}

54
main.go
View File

@ -3,43 +3,16 @@ package main
import "fmt"
func main() {
red := NewDummyPlayer(Red)
blue := NewDummyPlayer(Blue)
game := NewGame()
game.state = gameSetup
addpiece(game, 0, Blue, 0, 0)
addpiece(game, 1, Blue, 0, 1)
addpiece(game, 2, Blue, 1, 2)
addpiece(game, 3, Blue, 2, 4)
addpiece(game, 3, Blue, 1, 3)
addpiece(game, 4, Blue, 2, 6)
addpiece(game, 5, Blue, 3, 3)
addpiece(game, 9, Blue, 0, 6)
addpiece(game, 9, Blue, 0, 7)
addpiece(game, 0, Blue, 3, 5)
addriver(game, 3, 2)
addriver(game, 4, 2)
addriver(game, 3, 6)
addriver(game, 4, 6)
addpiece(game, 0, Red, 4, 0)
addpiece(game, 1, Red, 4, 1)
addpiece(game, 2, Red, 5, 2)
addpiece(game, 3, Red, 6, 4)
addpiece(game, 3, Red, 5, 3)
addpiece(game, 4, Red, 6, 6)
addpiece(game, 5, Red, 7, 3)
addpiece(game, 9, Red, 4, 5)
addpiece(game, 9, Red, 4, 7)
addpiece(game, 0, Red, 7, 5)
fmt.Printf("%v %v\n%v\n", red, blue, game)
game.Start()
//red := NewDummyPlayer(Red)
//blue := NewDummyPlayer(Blue)
g := NewGame()
g.state = gameSetup
printboardcolours(g)
return
}
func addpiece(game *Game, rank int, c Colour, x int, y int) {
res, err := game.SetupPiece(x, y, NewPiece(rank, c))
res, err := game.SetupPiece(x, y, NewPieceFromInt(rank, c))
if err != nil {
panic(err)
}
@ -57,3 +30,18 @@ func addriver(game *Game, x int, y int) {
panic("can't river")
}
}
func printboardcolours(g *Game) {
for i := range g.board.board {
for j := range g.board.board[i] {
c := "X"
if g.board.board[i][j].colour == Red {
c = "R"
} else if g.board.board[i][j].colour == Blue {
c = "B"
}
fmt.Printf("%v", c)
}
fmt.Println("")
}
}

View File

@ -13,6 +13,7 @@ const (
Captain
General
Marshal
Bomb
)
//Piece :game piece
@ -22,8 +23,8 @@ type Piece struct {
Hidden bool
}
//NewPiece creates a new piece
func NewPiece(r int, o Colour) *Piece {
//NewPieceFromInt creates a new piece
func NewPieceFromInt(r int, o Colour) *Piece {
return &Piece{
Rank: Rank(r),
Owner: o,
@ -31,6 +32,15 @@ func NewPiece(r int, o Colour) *Piece {
}
}
//NewPiece generates a piece by rank
func NewPiece(r Rank, o Colour) *Piece {
return &Piece{
Rank: r,
Owner: o,
Hidden: false,
}
}
//NewHiddenPiece creates a new hidden piece
func NewHiddenPiece(o Colour) *Piece {
return &Piece{

View File

@ -7,9 +7,9 @@ import (
"fmt"
)
const _RankName = "FlagSpyScoutMinerCaptainGeneralMarshal"
const _RankName = "FlagSpyScoutMinerCaptainGeneralMarshalBomb"
var _RankIndex = [...]uint8{0, 4, 7, 12, 17, 24, 31, 38}
var _RankIndex = [...]uint8{0, 4, 7, 12, 17, 24, 31, 38, 42}
func (i Rank) String() string {
if i < 0 || i >= Rank(len(_RankIndex)-1) {
@ -18,7 +18,7 @@ func (i Rank) String() string {
return _RankName[_RankIndex[i]:_RankIndex[i+1]]
}
var _RankValues = []Rank{0, 1, 2, 3, 4, 5, 6}
var _RankValues = []Rank{0, 1, 2, 3, 4, 5, 6, 7}
var _RankNameToValueMap = map[string]Rank{
_RankName[0:4]: 0,
@ -28,6 +28,7 @@ var _RankNameToValueMap = map[string]Rank{
_RankName[17:24]: 4,
_RankName[24:31]: 5,
_RankName[31:38]: 6,
_RankName[38:42]: 7,
}
// RankString retrieves an enum value from the enum constants string name.