Here's my overly complicated player.
http://members.iinet.net.au/~soxbox/ruby_quiz_51/
Designing an AI for a game which you've never played is a pretty
daunting task. I created a RulePlayer that evaluates each possible card
based on Rules. I then created a bunch of rules that seemed to make
sense to me. However, I didn't know enough to be able to prioritize my
rules. Never playing the game, I don't know what strategies work, and
which ones fall on their faces. So I let the computer do the work with a
little bit of genetics.
The rule_player.rb file contains the basic framework for parsing the
input and storing the knowledge and also the rules, as well as an extra
player named "MultiplierPlayer" which allows the rules to be given
different weightings
The breeder.rb file contains the breeding system. It creates a bunch of
MultiplierPlayers with different weightings and plays them against each
other round-robin style. The 2 players with the most wins under their
belts get bred to form extra players and the worst players get dropped.
The players are then saved off in a yaml file. Being yaml, it's easy to
edit, so if you think you know better than the breeder, it's easy to
throw your figures into the race.
The bred_player.rb loads up the data from the yaml file into a player
suitable for use with the game.
The lost_cities_test.rb file is almost the same as that posted earlier -
it pits players against each other in much the same way as the breeder
file does - I just made it ignore players that require arguments to
initialize, so that I could have the RulePlayer and MultiplierPlayer
ignored.
After a few rounds of breeding, it seems that the only rules of any
worth that I picked up are PlayLowestFirst and MaximumScoreEndGame. I
tried manually introducing some of the other rules, but they kept on
getting bred out. Both of those a rules only affecting the playing of
cards - it seems that my rules affecting the drawing and discarding of
cards are pretty much useless, or just aren't being given the right
weighting.
Rules::PlayLowestFirst 1.0000
Rules::MaximumScoreEndGame 1.0000
Rules::IgnoreUnusable 0.0000
Rules::DiscardUnusable 0.0000
Rules::DepriveOpponent 0.0000
Rules::AvoidLateInvestment 0.0000
Rules::ExpectedInvestmentValue 0.0000
Things to note:
- The KnownGame class keeps track of any cards the opponent
picks up, so that you know part of the opponent's hand. My rules don't
take advantage of this, but I think it would be great if used wisely.
- The breeder plays only 5 games with each pairing, and uses the
same 5 decks across all pairings (by using random seeds). This might
result in players getting dismissed due to an unlucky deck, but it runs
too slowly to up it any further.
- If the game takes longer than 300 turns, it's considered a
writeoff, and the players involved are put at the end of the list - this
is usually because both player is a little bit enthusiastic about
picking up discards, and nobody draws from the deck. I don't know if
this will affect legitimate strategies.
- This type of system is notorious for breeding players that are
good at playing against themselves. I always check the player in a
series of known games against dumb_player.rb to make sure that it's
actually degenerating in general play.
It seems to come out pretty well against DumbPlayer, and kicks
RiskPlayer's butt (who always seems to get beaten by DumbPlayer too).
> ruby lost_cities_test.rb 100 543991 dumb_player.rb bred_player.rb
Class Wins Avg. Min. Max.
BredPlayer 55 -2.19 -81.00 47.00
DumbPlayer 45 -9.40 -74.00 78.00
> ruby lost_cities_test.rb 10 543991 dumb_player.rb risk_player
> bred_player.rb
Class Wins Avg. Min. Max.
BredPlayer 14 -4.85 -74.00 29.00
DumbPlayer 13 -19.20 -73.00 28.00
RiskPlayer 3 -60.95 -108.00 -22.00
#####################################################################################
This email has been scanned by MailMarshal, an email content filter.
#####################################################################################