Skip to content

Commit

Permalink
Merge branch 'master' into awoo-14
Browse files Browse the repository at this point in the history
  • Loading branch information
Sigafoos authored Oct 8, 2020
2 parents 39fdd84 + 6918c70 commit e5e40f1
Show file tree
Hide file tree
Showing 17 changed files with 628 additions and 299 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,21 @@ Play!

`A W O O`

## Dependencies (for development)
Install go and npm through your favorite means. Then install bindata and elm.

```
go get github.com/jteeuwen/go-bindata/...
go get github.com/elazarl/go-bindata-assetfs/...
npm i -g [email protected]
```

## How to build it (if you want to change the code)
The simplest, though most time consuming, option is to run:

make
```
make
```

That will run the testsuite, rebuild the assets and compile the code into the `./awoo` binary.

Expand Down
62 changes: 31 additions & 31 deletions bindata.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions chanmsg/activity.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package chanmsg
const (
Join = iota
SetName
GetRolesets
SetRoleset
PlayerList
Vote
Expand Down
4 changes: 1 addition & 3 deletions game/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ func (g *Game) NightAction(fp *FingerPoint) *ActionResult {

if fp.From.Role().HasNightKill() {
log.Printf("%s is killing %s", fp.From.Identifier(), fp.To.Identifier())
if !fp.To.Role().Kill() {
result.Killed = fp.To
}
result.Killed = fp.To
}

if fp.From.Role().ViewsForMax() {
Expand Down
12 changes: 0 additions & 12 deletions game/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,6 @@ func (suite *ActionTestSuite) TestNightKill() {
assert.Equal(suite.T(), suite.to, result.Killed)
}

// TestToughNightKill ensures that a wolf eating someone who doesn't die
// won't reveal the target
func (suite *ActionTestSuite) TestToughNightKill() {
suite.from.SetRole(role.Werewolf())
suite.to.SetRole(role.Villager())
suite.to.Role().Health = 2

result := suite.game.NightAction(&FingerPoint{suite.from, suite.to})
assert.Equal(suite.T(), "", result.PlayerMessage)
assert.Nil(suite.T(), result.Killed)
}

// TestKnowsMaxes tests that a role that is told who the wolves are will be told.
func (suite *ActionTestSuite) TestKnowsMaxes() {
suite.from.SetRole(role.Cultist())
Expand Down
42 changes: 31 additions & 11 deletions game/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ type Game struct {
Players map[string]player.Player `json:"-"`
PlayerList []player.Player `json:"players"`
Roleset *roleset.Roleset `json:"roleset"`
votes map[player.Player]string `json:"-"`
Tally []*tally.TallyItem `json:"tally"`
State int `json:"game_state"`
Phase int `json:"phase"`
NightActionQueue []*FingerPoint `json:"-"`
gameChan chan *chanmsg.Activity `json:"-"`
votes map[player.Player]string
gameChan chan *chanmsg.Activity
}

func New(joinChan chan player.Player) *Game {
Expand Down Expand Up @@ -88,6 +88,9 @@ func (g *Game) AddPlayer(p player.Player) error {
}

func (g *Game) ShouldStart() bool {
if g.Roleset != nil {
log.Printf("%v/%v players", len(g.Players), len(g.Roleset.Roles))
}
return g.Roleset != nil && len(g.Players) == len(g.Roleset.Roles)
}

Expand Down Expand Up @@ -181,6 +184,8 @@ func (g *Game) RebuildTally() {
func (g *Game) SetRoleset(r *roleset.Roleset) error {
if g.State != Setup {
return fmt.Errorf("cannot set roleset: game is not in 'not running' phase")
} else if len(r.Roles) < len(g.Players) {
return fmt.Errorf("roleset %s only has %v roles; %v players in lobby", r.Name, len(r.Roles), len(g.Players))
}

g.Roleset = r
Expand Down Expand Up @@ -245,11 +250,17 @@ func (g *Game) VotedOut() player.Player {
threshold++
}

votes := 0
var ousted player.Player
for _, item := range g.Tally {
votes += len(item.Votes)
if len(item.Votes) >= threshold {
return item.Candidate
ousted = item.Candidate
}
}
if votes == len(g.PlayerList) && ousted != nil {
return ousted
}
return nil
}

Expand Down Expand Up @@ -278,23 +289,24 @@ func (g *Game) ProcessStartActionQueue() {
}

func (g *Game) ProcessNightActionQueue() {
var deaths []*player.Revealed
var death *player.Revealed
for _, action := range g.NightActionQueue {
result := g.NightAction(action)
if result.PlayerMessage != "" {
action.From.Message(message.Private, result.PlayerMessage)
}
if result.Killed != nil {
deaths = append(deaths, action.To.Reveal())
action.To.Message(message.Dead, "")

// TODO maybe more than one death?
if result.Killed != nil && death == nil && !result.Killed.Role().Kill() {
death = result.Killed.Reveal()
result.Killed.Message(message.Dead, "")
}
}

g.NextPhase()

if len(deaths) > 0 {
// TODO maybe more than one death?
g.Broadcast(message.Targeted, deaths[0])
if death != nil {
g.Broadcast(message.Targeted, death)
}
}

Expand Down Expand Up @@ -364,10 +376,17 @@ func (g *Game) HandlePlayerMessage() {
log.Printf("%s: requesting tally", from.Identifier())
from.Message(message.Tally, tally.Short(g.Tally))

case chanmsg.GetRolesets:
log.Printf("%s: requesting available rolesets", from.Identifier())
from.Message(message.RolesetList, roleset.List())

case chanmsg.SetRoleset:
log.Printf("%s: setting roleset %s", from.Identifier(), activity.Roleset)
sets := roleset.List()
g.SetRoleset(sets[activity.Roleset])
if err := g.SetRoleset(sets[activity.Roleset]); err != nil {
log.Printf("error: %s", err)
from.Message(message.Error, err)
}

case chanmsg.Vote:
log.Printf("%s: voting for %s", from.Identifier(), g.Players[activity.To].Identifier())
Expand All @@ -382,6 +401,7 @@ func (g *Game) HandlePlayerMessage() {
To: to,
}
g.QueueNightAction(fp)

case chanmsg.ResetGame:
log.Printf("%s: resetting game", from.Identifier())
g.Reset()
Expand Down
12 changes: 6 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"log"
"net"
"net/http"
"os"

Expand All @@ -22,11 +23,10 @@ func main() {
}
http.Handle("/", http.FileServer(server))

file, err := os.OpenFile("werewolf.log", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
port := os.Getenv("PORT")
if port == "" {
port = "42300"
}
log.Println("running...")
log.SetOutput(file)
log.Fatal(http.ListenAndServe(":42300", nil))
log.Printf("running on port %s...\n", port)
log.Fatal(http.ListenAndServe(net.JoinHostPort("", port), nil))
}
1 change: 1 addition & 0 deletions message/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type ClientMessage struct {
Vote string `json:"voteFor"`
Time string `json:"time"`
Roleset string `json:"setRoleset"`
FetchRolesets bool `json:"fetchRolesets"`
Reset bool `json:"resetGame"`
}

Expand Down
31 changes: 16 additions & 15 deletions message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ import (
)

const (
Awoo = "awoo"
Role = "role"
PlayerList = "playerlist"
Roleset = "roleset"
GameState = "gamestate"
Phase = "phase"
Leader = "leader"
PleaseWait = "pleasewait" // they're in the lobby
CanNotJoin = "cannotjoin"
Tally = "tally"
Targeted = "targeted"
Victory = "victory"
Private = "privatemessage"
Dead = "dead"
Error = "error"
Awoo = "awoo"
Role = "role"
PlayerList = "playerlist"
Roleset = "roleset"
RolesetList = "rolesetlist"
GameState = "gamestate"
Phase = "phase"
Leader = "leader"
PleaseWait = "pleasewait" // they're in the lobby
CanNotJoin = "cannotjoin"
Tally = "tally"
Targeted = "targeted"
Victory = "victory"
Private = "privatemessage"
Dead = "dead"
Error = "error"
Reset = "reset"
)

Expand Down
4 changes: 2 additions & 2 deletions player/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ func (p *GamePlayer) Play() {
if m.JoinName != "" {
p.Name = m.JoinName

// I don't love that this happens here.
// TODO make that a separate request
p.joinChan <- p
} else if m.PollPlayerList {
p.gameChan <- chanmsg.New(chanmsg.PlayerList, p.ID())
} else if m.PollTally {
p.gameChan <- chanmsg.New(chanmsg.Tally, p.ID())
} else if m.FetchRolesets {
p.gameChan <- chanmsg.New(chanmsg.GetRolesets, p.ID())
} else if m.Roleset != "" {
activity := chanmsg.New(chanmsg.SetRoleset, p.ID())
activity.Roleset = m.Roleset
Expand Down
25 changes: 25 additions & 0 deletions role/roleset/basic_seven.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package roleset

import (
"github.com/awoo-detat/awoo/role"
)

func BasicSeven() *Roleset {
return &Roleset{
Name: "Basic Seven",
Description: "One wolf, one cultist",
Roles: []*role.Role{
role.Werewolf(),
role.Cultist(),
role.Villager(),
role.Villager(),
role.Villager(),
role.Villager(),
role.Villager(),
},
}
}

func init() {
registerRoleset(BasicSeven())
}
29 changes: 29 additions & 0 deletions role/roleset/imperfect_eleven.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package roleset

import (
"github.com/awoo-detat/awoo/role"
)

func ImperfectEleven() *Roleset {
return &Roleset{
Name: "Imperfect Eleven",
Description: "Two wolves and a semblance of balance.",
Roles: []*role.Role{
role.Werewolf(),
role.Werewolf(),
role.Sorcerer(),
role.Hunter(),
role.Seer(),
role.Villager(),
role.Villager(),
role.Villager(),
role.Villager(),
role.Villager(),
role.Villager(),
},
}
}

func init() {
registerRoleset(ImperfectEleven())
}
25 changes: 25 additions & 0 deletions role/roleset/less_basic_seven.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package roleset

import (
"github.com/awoo-detat/awoo/role"
)

func LessBasicSeven() *Roleset {
return &Roleset{
Name: "Less Basic Seven",
Description: "Seer and sorcerer, oh my!",
Roles: []*role.Role{
role.Werewolf(),
role.Sorcerer(),
role.Seer(),
role.Villager(),
role.Villager(),
role.Villager(),
role.Villager(),
},
}
}

func init() {
registerRoleset(LessBasicSeven())
}
Loading

0 comments on commit e5e40f1

Please sign in to comment.