were_wolf 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2bddf36a281f5189a36ae1c65dede53c43f567de
4
+ data.tar.gz: d0dae2add604f028fd24ef2fe791a677588f848f
5
+ SHA512:
6
+ metadata.gz: 6c2a9ef75b7441395bdb853dd2c3053bf125cb34fcc783ab8801b4844e5723ce9dbf97e60e5cf8e01cd86aefee9f43c03f6b0daaae2ed14edab63ce08144c4d3
7
+ data.tar.gz: cb47b1a687f2ebc9c06dff229f33ad5411bcbacda845f753449143d00ee19754b2c7cd400a28b103112e13bb69357b18ca2091f66c32dd0799356b6c4b038137
data/.gitignore ADDED
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ # Gemfile.lock
31
+ # .ruby-version
32
+ # .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in were_wolf.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 CodeAstra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # WereWolf
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/were_wolf`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'were_wolf'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install were_wolf
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/CodeAstra/were_wolf.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "were_wolf"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,102 @@
1
+ require_relative 'player/player_collection'
2
+
3
+ # game = Game.new(3, 9)
4
+ # game.simulate
5
+ class Game
6
+ DRAW = 0
7
+ WOLF = 1
8
+ VILLAGER = 2
9
+
10
+ def initialize(no_of_wolves, no_of_villagers)
11
+ @players = PlayerCollection.new(no_of_wolves, no_of_villagers)
12
+ end
13
+
14
+ def run
15
+ until over?
16
+ night_mode
17
+ day_mode unless over?
18
+ end
19
+
20
+ return DRAW if @draw
21
+
22
+ return villagers_alive.empty? ? WOLF : VILLAGER
23
+ end
24
+
25
+ private
26
+ def over?
27
+ villagers_alive.empty? || wolves_alive.empty?
28
+ end
29
+
30
+ def night_mode
31
+ # Cop identifies a person
32
+ cop = @players.cop
33
+ cop.identify_a_player(@players) if cop
34
+ # Doctor chooses to save a person
35
+ doctor = @players.doctor
36
+ saved_person = doctor.choose_a_player_to_save(@players)
37
+ # Wolves kill a villager
38
+ wolves_victim = villagers_alive.sample
39
+ # Rogue kills a players once in the entire game
40
+ rogue = @players.rogue
41
+ rogues_victim = rogue.choose_victim(@players) if rogue
42
+
43
+ # Don't kill the person if the doctor saved the person
44
+ @players.kill(wolves_victim) unless wolves_victim == saved_person
45
+ # Don't kill the person again, if the wolves have already killed the person
46
+ @players.kill(rogues_victim) unless (rogues_victim == saved_person) || (rogues_victim == wolves_victim)
47
+ end
48
+
49
+ def day_mode
50
+ victim = run_voting
51
+ if victim == DRAW
52
+ @draw = true
53
+ else
54
+ @players.kill(victim)
55
+ end
56
+ end
57
+
58
+ def run_voting
59
+ if (villagers_count == 1 && wolves_count == 1)
60
+ return DRAW
61
+ end
62
+
63
+ votes = Hash.new(0)
64
+
65
+ players_alive.each do |player|
66
+ accused = player.accuse(@players)
67
+ votes[accused] += 1
68
+ end
69
+
70
+ max_votes = votes.values.max
71
+ winners = []
72
+ votes.keys.each do |player|
73
+ winners.push(player) if votes[player] == max_votes
74
+ end
75
+
76
+ if winners.count == 1
77
+ return winners.first
78
+ else
79
+ return run_voting
80
+ end
81
+ end
82
+
83
+ def villagers_alive
84
+ @players.alive_villagers
85
+ end
86
+
87
+ def villagers_count
88
+ villagers_alive.count
89
+ end
90
+
91
+ def wolves_alive
92
+ @players.alive_wolves
93
+ end
94
+
95
+ def wolves_count
96
+ wolves_alive.count
97
+ end
98
+
99
+ def players_alive
100
+ @players.alive_players
101
+ end
102
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'game'
2
+
3
+ class GameSimulator
4
+ def initialize(no_of_wolves, no_of_villagers, no_of_runs)
5
+ @no_of_wolves = no_of_wolves
6
+ @no_of_villagers = no_of_villagers
7
+ @no_of_runs = no_of_runs
8
+ end
9
+
10
+ def simulate
11
+ wins = Hash.new(0)
12
+ @no_of_runs.times do
13
+ wins[Game.new(@no_of_wolves, @no_of_villagers).run] += 1
14
+ end
15
+
16
+ return wins
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ require_relative 'game'
2
+ require_relative 'game_simulator'
3
+
4
+ class GameSuggestor
5
+ def initialize(num_of_players, no_of_runs)
6
+ @players_count = num_of_players
7
+ @no_of_runs = no_of_runs
8
+ end
9
+
10
+ def run
11
+ # Preferred Wolves Win Percentage
12
+ pref_wolves_prob = 70
13
+ wolves_count = 1
14
+ absolute_diff = 1000
15
+ best_wins = {}
16
+
17
+ while true
18
+ wins = GameSimulator.new(wolves_count, @players_count - wolves_count, @no_of_runs).simulate
19
+ percent_wolves_win = (100.0*wins[Game::WOLF]/@no_of_runs)
20
+ new_diff = (pref_wolves_prob - percent_wolves_win).abs
21
+ if new_diff < absolute_diff
22
+ absolute_diff = new_diff
23
+ best_wins = wins
24
+ wolves_count += 1
25
+ else
26
+ return result(wolves_count - 1, best_wins)
27
+ end
28
+ end
29
+ end
30
+ private
31
+ def result(wolves_count, best_wins)
32
+ players = {}
33
+ players['wolves'] = wolves_count
34
+ players['cops'] = 1
35
+ players['doctors'] = 1 if @players_count - wolves_count > 1
36
+ players['rogues'] = 1 if @players_count - wolves_count > 2
37
+ players['villagers'] = (@players_count - wolves_count - 3) if @players_count - wolves_count > 3
38
+
39
+ probabilities = {}
40
+ probabilities['wolves_win'] = (100.0*(best_wins[Game::WOLF] || 0)/@no_of_runs)
41
+ probabilities['villagers_win'] = (100.0*(best_wins[Game::VILLAGER] || 0)/@no_of_runs)
42
+ probabilities['draws'] = (100.0*(best_wins[Game::DRAW] || 0)/@no_of_runs)
43
+
44
+ hsh = {players: players, probabilities: probabilities}
45
+
46
+ return hsh
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'wolf'
2
+
3
+ class Cop < Villager
4
+ def initialize
5
+ super
6
+ forget_all
7
+ end
8
+
9
+ def identify_a_player(players)
10
+ identified_player = (players.alive_players - @identified_wolves - @identified_villagers - [self]).sample
11
+ if identified_player.is_a?(Wolf)
12
+ @identified_wolves.push(identified_player)
13
+ else
14
+ @identified_villagers.push(identified_player)
15
+ end
16
+ end
17
+
18
+ def accuse(players)
19
+ if @identified_wolves.any?
20
+ return @identified_wolves.sample
21
+ else
22
+ return (players.alive_players - [self] - @identified_villagers).sample
23
+ end
24
+ end
25
+
26
+ def forget_all
27
+ @identified_wolves = []
28
+ @identified_villagers = []
29
+ end
30
+
31
+ def forget(player)
32
+ if player.is_a?(Wolf)
33
+ @identified_wolves.delete(player)
34
+ else
35
+ @identified_villagers.delete(player)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ class Doctor < Villager
2
+ def choose_a_player_to_save(players)
3
+ # Assumption: Doctor saves him/her self 50% of the times
4
+ if rand < 0.5
5
+ return self
6
+ else
7
+ return players.alive_players.sample
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,2 @@
1
+ class Player
2
+ end
@@ -0,0 +1,87 @@
1
+ require_relative 'wolf'
2
+ require_relative 'villager'
3
+ require_relative 'cop'
4
+ require_relative 'doctor'
5
+ require_relative 'rogue'
6
+
7
+ class PlayerCollection
8
+ def initialize(no_of_wolves, no_of_villagers)
9
+ @players = []
10
+ @wolves = []
11
+ @villagers = []
12
+ no_of_wolves.times do
13
+ wolf = Wolf.new
14
+ @wolves.push(wolf)
15
+ @players.push(wolf)
16
+ end
17
+ @villagers = []
18
+ (1..no_of_villagers).each do |i|
19
+ if i == 1
20
+ villager = Cop.new
21
+ @cop = villager
22
+ elsif i == 2
23
+ villager = Doctor.new
24
+ @doctor = villager
25
+ elsif i == 3
26
+ villager = Rogue.new
27
+ @rogue = villager
28
+ else
29
+ villager = Villager.new
30
+ end
31
+ @villagers.push(villager)
32
+ @players.push(villager)
33
+ end
34
+ end
35
+
36
+ def alive_villagers
37
+ @villagers
38
+ end
39
+
40
+ def alive_wolves
41
+ @wolves
42
+ end
43
+
44
+ def alive_players
45
+ @players
46
+ end
47
+
48
+ def kill(player)
49
+ if player.is_a?(Wolf)
50
+ collection = @wolves
51
+ promote_rogue_to_wolf
52
+ else
53
+ @cop = nil if player.is_a?(Cop)
54
+ @rogue = nil if player.is_a?(Rogue)
55
+ collection = @villagers
56
+ end
57
+ collection.delete(player)
58
+ @players.delete(player)
59
+ @cop.forget(player) if @cop
60
+ end
61
+
62
+ def cop
63
+ @cop
64
+ end
65
+
66
+ def doctor
67
+ @doctor
68
+ end
69
+
70
+ def rogue
71
+ @rogue
72
+ end
73
+
74
+ private
75
+ def promote_rogue_to_wolf
76
+ return if @wolves.count > 0
77
+
78
+ if @rogue
79
+ kill(@rogue)
80
+ new_wolf = Wolf.new
81
+ @wolves.push(new_wolf)
82
+ @players.push(new_wolf)
83
+ end
84
+
85
+ @cop.forget_all!
86
+ end
87
+ end
@@ -0,0 +1,19 @@
1
+ class Rogue < Villager
2
+ def initialize
3
+ super
4
+ @killing_power_used = false
5
+ end
6
+
7
+ def choose_victim(players)
8
+ return nil if @killing_power_used
9
+
10
+ if (rand < (1.0/(players.alive_wolves.count + 1)))
11
+ # Choose a victim
12
+ @killing_power_used = true
13
+ return (players.alive_players - [self]).sample
14
+ else
15
+ # Save the power for a later round
16
+ return nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'player'
2
+
3
+ class Villager < Player
4
+ def accuse(players)
5
+ (players.alive_players - [self]).sample
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'player'
2
+
3
+ class Wolf < Player
4
+ def accuse(players)
5
+ players.alive_villagers.sample
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module WereWolf
2
+ VERSION = "0.1.0"
3
+ end
data/lib/were_wolf.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'were_wolf/version'
2
+ require 'were_wolf/game'
3
+ require 'were_wolf/game_simulator'
4
+ require 'were_wolf/game_suggestor'
5
+
6
+ module WereWolf
7
+ class << self
8
+ # Return:
9
+ # => 0 if the game is draw
10
+ # => 1 if wolves win
11
+ # => 2 if villagers win
12
+ def run(wolves_count, villagers_count)
13
+ game = Game.new(wolves_count, villagers_count)
14
+ return game.run
15
+ end
16
+
17
+ # Returns a hash with the following keys and value pairs:
18
+ # => 0, <no of draws>
19
+ # => 1, <no of tiems wolves won>
20
+ # => 2, <no of tiems vilalgers won>
21
+ def simulate(wolves_count, villagers_count, runs_count = 100)
22
+ simulator = GameSimulator.new(wolves_count, villagers_count, runs_count)
23
+ return simulator.simulate
24
+ end
25
+
26
+ def suggest(players_count, runs_count = 100)
27
+ suggestor = GameSuggestor.new(players_count, runs_count)
28
+ return suggestor.run
29
+ end
30
+ end
31
+ end
data/were_wolf.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'were_wolf/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "were_wolf"
8
+ spec.version = WereWolf::VERSION
9
+ spec.authors = ["BV Satyaram"]
10
+ spec.email = ["bvsatyaram@gmail.com"]
11
+
12
+ spec.summary = "WereWolf Game helper"
13
+ spec.description = "Provide us the number of players, we suggest the config for the game"
14
+ spec.homepage = "http://www.codeastra.com"
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.10"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: were_wolf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - BV Satyaram
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Provide us the number of players, we suggest the config for the game
42
+ email:
43
+ - bvsatyaram@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - bin/console
54
+ - bin/setup
55
+ - lib/were_wolf.rb
56
+ - lib/were_wolf/game.rb
57
+ - lib/were_wolf/game_simulator.rb
58
+ - lib/were_wolf/game_suggestor.rb
59
+ - lib/were_wolf/player/cop.rb
60
+ - lib/were_wolf/player/doctor.rb
61
+ - lib/were_wolf/player/player.rb
62
+ - lib/were_wolf/player/player_collection.rb
63
+ - lib/were_wolf/player/rogue.rb
64
+ - lib/were_wolf/player/villager.rb
65
+ - lib/were_wolf/player/wolf.rb
66
+ - lib/were_wolf/version.rb
67
+ - were_wolf.gemspec
68
+ homepage: http://www.codeastra.com
69
+ licenses: []
70
+ metadata:
71
+ allowed_push_host: https://rubygems.org
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.4.8
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: WereWolf Game helper
92
+ test_files: []