Sophie

Sophie

distrib > Fedora > 14 > x86_64 > media > updates > by-pkgid > c2689b4ec379fa0c27c46f80bcedfcf3 > files > 25

colossus-0.12.1-1.fc14.noarch.rpm

We need to teach the AI to predict enemy stack contents, without peeking.

The general stack prediction algorithm will use one binary tree per enemy 
player.  (Binary because all splits in Colossus are binary -- Titan allows 
a 3-way split but Colossus models it as two splits.)  Each parent loosely 
represents a pre-split legion.  Each child node represents a post-split legion.  
Each node contains a legion ID string and a list of creature names.

Each creature has two flags.  The first says whether its presence in this 
legion is certain or a guess.  The second says whether this legion was in 
this stack at the time it was split, or was added to one of its children later.  
(We need a historical record of stack contents at the time of splits so that 
we can re-predict splits later.  The alternative is always generating and 
saving an exhaustive list of all possible splits.  But that's just not 
practical because sometimes we don't know all contents of a splitting legion.)
The leaf legions are the legions currently on the board -- the rest are legions
that used to exist.  Note that because one of the split legions keeps the
parent's legion marker, we need to use tree position not just marker id to
refer to legions.

The creatures in a parent node must match the creatures in its child nodes.  
(In name, but not necessarily in visibility.)  Each time a creature is added 
or removed, this is done in both places.  Angel summoning is a special case, 
but to keep things consistent we move the angel in the parents as well.

Whenever an opponent splits, the AI uses its split function to predict the split.  
So after Black's opening split, another player's tree for Black might look like:

(Notation: ? means we're not certain about this creature's location.  * means
that this creature has been added since this legion was split off -- its location
is known and it wasn't in the parent so we don't need to consider it when we
redo split predictions.)

                        Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

                Bk01 Tit?,Ogr?,Ogr?,Gar?     Bk02   Ang?,Cen?,Cen?,Gar?

Black rolls a 6.  Bk02 teleports to another tower, showing a Titan.  Oops -- we 
guessed wrong.  The AI split function needs to be modified to return multiple 
possible splits in descending order of how "good" they are, not just one split.
(We'll use a permutation generator to find all of them, then score each one
and sort them by score.  Luckily there aren't very many -- for the worst case 
where a 7-high legion with all the creatures different splits 4-3 there are 
only 7 * 6 * 5 = 210 possible splits.)

Then we can iterate through them until we find the first/best one that puts the 
Titan in Bk02, and use that for our current prediction.

                        Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

                Bk01 Ang,Ogr?,Ogr?,Gar?     Bk02   Tit,Cen?,Cen?,Gar?

Bk02 recruits a warlock in the tower, with the Titan.  This is consistent with the 
current expected contents of the legion, so all we do is add the warlock to the
child.  (Again, the * shows that the creature was added since the last split.)

                        Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

                Bk01 Ang,Ogr?,Ogr?,Gar?  Bk02  Tit,Cen?,Cen?,Gar?,Wlk*

Bk01 recruits a lion in the plains with two centaurs.  Oops, we didn't think Bk01 
had any centaurs.  Back through the possible splits again, until we find one that 
matches all known creatures.

                      Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

                Bk01 Ang,Cen,Cen,Lio*,Gar?  Bk02  Tit,Ogr?,Ogr?,Gar?,Wlk*

Now here's where we gain information by simple subtraction.  There are two ogres 
and two gargoyles unaccounted for.  One of those creatures is in Bk01; the other 
three are in Bk02.  It should be obvious that Bk02 must contain at least one Ogr 
and one Gar.  (We need to either explicitly code this subtractive logic, or else 
iterate through all possible splits that fit the known facts and mark things that
are common to all of them as known.)  So:

                        Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

                Bk01 Ang,Cen,Cen,Lio*,Gar?  Bk02  Tit,Ogr,Ogr?,Gar,Wlk*

In Black's second turn, Bk01 moves to a plains and recruits another Lion.  Bk02 
moves to the brush and recruits a Cyclops with two gargoyles.  So we need to 
re-predict the split again and find one where Bk02 contained two gargoyles.
There is only one possibility, so the location of all creatures is now known:

                  Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr  Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*

At this point the parent node's split is definitely known.  We should never
need to refer back to the parent node again.  Deleting it would leave our
tree headless, though, and these nodes don't use much memory, so we probably
just keep it around.

In Black's third turn, nothing splits.  Bk01 recruits a Ranger, and Bk02
recruits another Clops.

                  Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran*  Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc*

In Black's fourth turn, each legion splits 5-2.  We predict:

                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran*                         Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc*

Bk01 Ang?,Ran?,Lio?,Lio?,Ogr?    Bk03 Cen?,Cen?         Bk02 Tit?,Wlk?,Cyc?,Cyc?,Ogr?    Bk04  Gar?,Gar?


Bk01 jumps onto one of our 2-high splitoffs in the plains.  It is revealed 
(to us, but not to other players) as Ang,Ran,Lio,Lio,Ogr.  We mark both Bk01
and Bk03 as fully known.  We flee, so other players don't have this info.

                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran*                         Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc*

Bk01 Ang,Ran,Lio,Lio,Ogr    Bk03 Cen,Cen                   Bk02 Tit?,Wlk?,Cyc?,Cyc?,Ogr?    Bk04  Gar?,Gar?

Bk02 also gets aggressive, jumping onto another player's 4-high legion in the brush.
This player does not flee and a battle starts.  Both combatant legions are shown to
all players -- we see that Bk02 actually contained a Gar not an Ogr.  This leaves only
one possible split, so we also know the contents of Bk04.


                                    Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran*                         Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc*

Bk01 Ang,Ran,Lio,Lio,Ogr    Bk03 Cen,Cen                        Bk02 Tit,Wlk,Cyc,Cyc,Gar    Bk04  Gar,Ogr

During the fight, Bk02 loses one Clops and one Gargoyle, and summons the Angel.

                                    Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran*                         Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc*

Bk01 Ran,Lio,Lio,Ogr       Bk03 Cen,Cen                          Bk02 Tit,Wlk,Cyc,Ang*    Bk04  Gar,Ogr

Note that the summoned angel and dead creatures are no longer in the legions where
they used to live.  But if we ever needed to predict those splits (we don't in this
case because all legions are fully known), we'd need to account for them.  There
is almost enough information here to do that -- we can tell which creatures split
and then were eliminated by comparing the contents of the parent legion to the
sum of its children's contents.  We also need to note that each split was 5-2, and
which marker got which number of creatures.  This infomation goes in the parent, not
the children, because that way if a child legion is eliminated we can remove it from
the tree without losing this information.

Black recruits in the two larger legions:

                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran*                         Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc*

Bk01 Ran,Lio,Lio,Ogr,Ran*    Bk03 Cen,Cen                          Bk02 Tit,Wlk,Cyc,Ang*,Cyc*  Bk04  Gar,Ogr


Two turns and a few recruits later, Black has:


                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar (4-4)

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran* (5-2)                     Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc* (5-2)

Bk01 Ran,Lio,Lio,Ogr,Ran*,Lio*,Ran*    Bk03 Cen,Cen,Lio*            Bk02 Tit,Wlk,Cyc,Ang*,Cyc*,Cyc*  Bk04  Gar,Ogr,Ogr*,Tro*

On the next turn Bk01 splits:

                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar (4-4)

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran* (5-2)                     Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc* (5-2)

Bk01 Ran,Lio,Lio,Ogr,Ran*,Lio*,Ran* (5-2)   Bk03 Cen,Cen,Lio*      Bk02 Tit,Wlk,Cyc,Ang*,Cyc*,Cyc*  Bk04  Gar,Ogr,Ogr*,Tro*

Bk01 Ran?,Ran?,Ran?,Lio?,Lio?   Bk05 Lio?,Ogr?


Bk01 recruits a Griffon with 3 lions.  We re-predict and get:


                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar (4-4)

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran* (5-2)                     Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc* (5-2)

Bk01 Ran,Lio,Lio,Ogr,Ran*,Lio*,Ran* (5-2)   Bk03 Cen,Cen,Lio*      Bk02 Tit,Wlk,Cyc,Ang*,Cyc*,Cyc*  Bk04  Gar,Ogr,Ogr*,Tro*

Bk01 Ran?,Ran?,Lio,Lio,Lio,Gri*  Bk05 Ran?,Ogr?

But note that with 3 rangers and an ogre uncertain and Bk05 only 2-high, each 
of Bk01 and Bk05 must contain a ranger.


                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar (4-4)

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran* (5-2)                     Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc* (5-2)

Bk01 Ran,Lio,Lio,Ogr,Ran*,Lio*,Ran* (5-2)   Bk03 Cen,Cen,Lio*      Bk02 Tit,Wlk,Cyc,Ang*,Cyc*,Cyc*  Bk04  Gar,Ogr,Ogr*,Tro*

Bk01 Ran,Ran?,Lio,Lio,Lio,Gri*  Bk05 Ran,Ogr?


A 7-high stack jumps on Bk05, and it flees, revealing that it indeed 
contained Ran,Ogr.  Now Bk01's contents are known:


                              Bk01 Tit,Ang,Ogr,Ogr,Cen,Cen,Gar,Gar (4-4)

         Bk01 Ang,Cen,Cen,Lio*,Lio*,Ogr,Ran* (5-2)                     Bk02  Tit,Ogr,Gar,Gar,Wlk*,Cyc*,Cyc* (5-2)

Bk01 Ran,Lio,Lio,Ogr,Ran*,Lio*,Ran* (5-2)   Bk03 Cen,Cen,Lio*      Bk02 Tit,Wlk,Cyc,Ang*,Cyc*,Cyc*  Bk04  Gar,Ogr,Ogr*,Tro*

Bk01 Ran,Ran,Lio,Lio,Lio,Gri*