func (t propertyType) ZeroValue() string {
	switch t.PropertyType {
	case boardgame.TypeBool:
		return "false"
	case boardgame.TypeInt:
		return "0"
	case boardgame.TypeString:
		return "\"\""
	case boardgame.TypePlayerIndex:
		return "0"
	case boardgame.TypeIllegal:
		return ""
	}
	if t.IsSlice() {
		return t.ImmutableGoType() + "{}"
	}
	if t.IsInterface() {
		return "nil"
	}
	log.Println("Unexpected type for ZeroValue")
	return ""
}
ZeroValue returns the string representing the zeroValue for this type, e.g.
"0" for TypeInt and "[]boardgame.PlayerIndex{}" for TypePlayerIndexSlice. Most
useful for codgen package.
package codegen
import (
	"log"
	"strings"
	"github.com/jkomoros/boardgame"
)
var allValidTypes []propertyType
var typeNamesToFieldInfo map[string]fieldInfo
const highestProperty = boardgame.TypeTimer
func init() {
	allValidTypes = make([]propertyType, highestProperty)
	for i := 0; i < int(highestProperty); i++ {
		allValidTypes[i] = propertyType{boardgame.PropertyType(i + 1)}
	}
	typeNamesToFieldInfo = buildTypeNameMap()
}
func buildTypeNameMap() map[string]fieldInfo {
	result := make(map[string]fieldInfo)
	for _, t := range allValidTypes {
		result[t.ImmutableGoType()] = fieldInfo{
			Type:    t,
			Mutable: false,
		}
		result[t.MutableGoType()] = fieldInfo{
			Type:    t,
			Mutable: true,
		}
		for _, name := range t.ImmutableSubTypes() {
			result[name] = fieldInfo{
				Type:    t,
				Mutable: false,
				SubType: strings.TrimPrefix(name, t.TypePackagePrefix()),
			}
		}
		for _, name := range t.MutableSubTypes() {
			result[name] = fieldInfo{
				Type:    t,
				Mutable: true,
				SubType: strings.TrimPrefix(name, t.TypePackagePrefix()),
			}
		}
	}
	return result
}
func fieldInfoForTypeName(fieldTypeName string, isSlice bool) fieldInfo {
	key := fieldTypeName
	if isSlice {
		key = "[]" + key
	}
	return typeNamesToFieldInfo[key]
}
type propertyType struct {
	boardgame.PropertyType
}
func (t propertyType) TypePackagePrefix() string {
	base := t.BaseType()
	switch base {
	case boardgame.TypePlayerIndex, boardgame.TypeStack, boardgame.TypeBoard, boardgame.TypeTimer:
		return "boardgame."
	case boardgame.TypeEnum:
		return "enum."
	}
	return ""
}
func (t propertyType) ImmutableGoType() string {
	if t.IsSlice() {
		return "[]" + propertyType{t.BaseType()}.ImmutableGoType()
	}
	switch t.PropertyType {
	case boardgame.TypeBool:
		return "bool"
	case boardgame.TypeInt:
		return "int"
	case boardgame.TypeString:
		return "string"
	case boardgame.TypePlayerIndex:
		return "boardgame.PlayerIndex"
	case boardgame.TypeEnum:
		return "enum.ImmutableVal"
	case boardgame.TypeStack:
		return "boardgame.ImmutableStack"
	case boardgame.TypeBoard:
		return "boardgame.ImmutableBoard"
	case boardgame.TypeTimer:
		return "boardgame.ImmutableTimer"
	default:
		return ""
	}
}
func (t propertyType) MutableGoType() string {
	return strings.Replace(t.ImmutableGoType(), "Immutable", "", -1)
}
func (t propertyType) Key() string {
	return strings.TrimPrefix(t.String(), "Type")
}
func (t propertyType) ImmutableSubTypeConverters() []string {
	switch t.PropertyType {
	case boardgame.TypeStack:
		return []string{"MergedStack", "ImmutableSizedStack"}
	case boardgame.TypeEnum:
		return []string{"ImmutableTreeVal", "ImmutableRangeVal"}
	}
	return nil
}
func (t propertyType) MutableSubTypeConverters() []string {
	switch t.PropertyType {
	case boardgame.TypeStack:
		return []string{"SizedStack"}
	case boardgame.TypeEnum:
		return []string{"TreeVal", "RangeVal"}
	}
	return nil
}
func (t propertyType) ImmutableSubTypes() []string {
	prefix := t.TypePackagePrefix()
	var result []string
	for _, item := range t.ImmutableSubTypeConverters() {
		result = append(result, prefix+item)
	}
	return result
}
func (t propertyType) MutableSubTypes() []string {
	prefix := t.TypePackagePrefix()
	var result []string
	for _, item := range t.MutableSubTypeConverters() {
		result = append(result, prefix+item)
	}
	return result
}