Created
February 10, 2012 12:43
-
-
Save pasberth/1789427 to your computer and use it in GitHub Desktop.
かなり雑だけど張っておく 擬似的な生態系を作ってみる
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
module Ecosys | |
extend self | |
class FoodWeb | |
def initialize | |
@creatures = [] | |
@mutual = [] | |
end | |
attr_reader :creatures | |
attr_reader :mutual | |
def inspect | |
@creatures.map do |c| | |
filter(c).map(&:inspect).join "\n" | |
end.join "\n\n#{'='*40}\n" | |
end | |
def << creature | |
add_creature creature | |
add_mutual creature | |
creature | |
end | |
def filter c, d=nil | |
r = @mutual.select { |m| m.c == c or m.d == c } | |
return r if d.nil? | |
r.select { |m| m.c == d or m.d == d } | |
end | |
def changed c | |
# 絶滅 | |
if c.n <= 0 | |
@creatures.delete c | |
@mutual.delete_if do |m| | |
m.c == c or m.d == c | |
end | |
end | |
end | |
def add_mutual c | |
@creatures.each do |d| | |
if c.descent.nil? | |
@mutual << Mutual.new(c, d, Effect.friend) | |
next | |
end | |
# 近縁の種であれば共生を選択する | |
if c == d or c.descent == d or c.descent.ascents.include? d | |
@mutual << Mutual.new(c, d, Effect.friend) | |
next | |
end | |
# 近隣の種でなくなったら性質をランダムに変更する | |
if c.descent.descent.nil? or c.descent.descent == d or c.descent.descent.ascents.include? d | |
@mutual << Mutual.new(c, d, Effect.sample) | |
next | |
end | |
desm = c.descent.mutualof d | |
if desm.nil? | |
@mutual << Mutual.new(c, d, Effect.sample) # 通常ここは処理されない | |
elsif rand(4) == 0 | |
@mutual << Mutual.new(c, d, Effect.sample) # 一部の性質は変化する | |
else | |
@mutual << Mutual.new(c, d, desm.effect) # 基本的には親の性質を受け継ぐ | |
end | |
end | |
end | |
def add_creature c | |
@creatures << c | |
end | |
private :add_mutual, :add_creature | |
class Effect | |
def initialize text, &action | |
@text = text | |
@action = action | |
end | |
def call *a, &b | |
@action.call *a, &b | |
end | |
def to_s | |
@text | |
end | |
def to_proc | |
@action | |
end | |
FRIEND = Effect.new "they are friend." do |c, d| | |
if [true, false].sample then | |
c.n -= 1 | |
c.food_web.changed c | |
d.breed | |
else | |
d.n -= 1 | |
d.food_web.changed d | |
c.breed | |
end | |
end | |
def self.friend | |
[FRIEND].sample | |
end | |
LEFT_EAT = Effect.new "left eat right" do |c, d| | |
c.eat d | |
end | |
RIGHT_EAT = Effect.new "right eat left" do |c, d| | |
d.eat c | |
end | |
SYMBIOSIS = Effect.new "symbiosis" do |c, d| | |
c.breed | |
d.breed | |
end | |
def self.sample | |
[LEFT_EAT, RIGHT_EAT, SYMBIOSIS].sample | |
end | |
end | |
class Mutual | |
def initialize c, d, effect | |
@c = c | |
@d = d | |
@effect = effect | |
end | |
attr_reader :c, :d | |
attr_reader :effect | |
def call | |
effect.call c, d | |
end | |
def inspect | |
"#{@c}, #{@d}; #{@effect}" | |
end | |
def to_proc | |
method(:call).to_proc | |
end | |
end | |
end | |
class Creature | |
NAMES = [ | |
'ar', 'af', 'dor', 'imd', 'rus', 'wa', 'fa', 'wi', 'mma', 'be', 'ry', 'jara', 'je' | |
] | |
def initialize descent=nil, n=1 | |
@n = 1 | |
if descent.nil? | |
@descent = nil | |
@name = '' | |
@name_words = [] | |
@food_web = FoodWeb.new | |
@food_web << self | |
return | |
end | |
@descent = descent | |
if descent.name_words.length > 6 | |
[descent.name_words[1..-1], NAMES.sample].tap do |oldn, newn| | |
@name = oldn.join + newn | |
@name_words = oldn + [newn] | |
end | |
else | |
NAMES.sample.tap do |newn| | |
@name = descent.name + newn | |
@name_words = descent.name_words + [newn] | |
end | |
end | |
@food_web = descent.food_web | |
@food_web << self | |
end | |
def eat other | |
other.n -= 1 | |
breed | |
food_web.changed other | |
food_web.changed self | |
self | |
end | |
def breed | |
if rand(7) > 0 # 1/7 で進化 | |
self.n += 1 | |
self | |
else | |
create | |
end | |
end | |
def create | |
Creature.new self | |
end | |
def ascents | |
@food_web.creatures.select do |c| | |
c.descent == self | |
end | |
end | |
def mutualof d | |
@food_web.filter(self, d).first | |
end | |
def to_s | |
inspect | |
end | |
def inspect | |
"<#[#{@n}]: #{@name} from #{@descent.name if @descent}:C>" | |
end | |
attr_accessor :n | |
attr_reader :name, :name_words | |
attr_reader :descent | |
attr_reader :food_web | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
require './ecosys' | |
include Ecosys | |
common_descent = Creature.new nil, 10 | |
# 最初の生物を生み出す | |
5.times do | |
a = Creature.new common_descent, 10 | |
4.times do | |
b = Creature.new a, 10 | |
5.times do | |
c = Creature.new b, 10 | |
end | |
end | |
end | |
food_web = common_descent.food_web | |
c = 100 | |
loop do | |
food_web.mutual.sample.call | |
c -= 1 | |
if c < 0 | |
c = 100 | |
puts "="*40 | |
puts food_web.creatures.join "\n" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment