• Facebook
  • Twitter
  • Reddit
  • StumbleUpon
  • Digg
  • email

#------------------------------------------------------------------------------
# Copyright (C) 2007 Richard W. Lincoln
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 dated June, 1991.
#
# This software is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#------------------------------------------------------------------------------
 
"""
Filling of the boat follows the game rules, but we do not verify whether
someone can be eaten on either bank.
 
Negative reward will be assign in such cases.
 
Congo only generates non-eating moves.
 
"""
 
#------------------------------------------------------------------------------
#  Imports:
#------------------------------------------------------------------------------
 
# Standard library imports.
import logging
 
# Pyqle imports:
from pyqle.environment.action_list import ActionList
 
# Local imports:
from congo import Congo
 
from missionary_action import MissionaryAction
 
# Setup a logger for this module.
logger = logging.getLogger(__name__)
 
#------------------------------------------------------------------------------
#  "Brazzaville" class:
#------------------------------------------------------------------------------
 
class Brazzaville(Congo):
    """
    Filling of the boat follows the game rules, but we do not verify whether
    someone can be eaten on either bank.
 
    Negative reward will be assign in such cases.
 
    Congo only generates non-eating moves.
 
    """
 
    def is_final(self, e):
        """
        A state is final either because everybody is safe on the right bank, 
        or because someone eated someone else.
 
        """
 
        b = False
        em = e
        m = em.get_missionaries()
        c = em.get_cannibals()
        if not em.get_bank() and (m == 0) and (c == 0):
            b = True
        if c > m and (m != 0):
            b = True
        if self.population - c > self.population - m and \
        (self.population - m != 0):
            b = True
        return b
 
 
    def get_reward(self, s1, s2, a):
        """
        @return 1 if everybody is safe.
        @return -1 is someone is eaten
        @return 0 otherwise
 
        """
 
        if not self.is_final(s2):
            return -1
        em = s2
        m = em.get_missionaries()
        c = em.get_cannibals()
        if (m == 0) and (c == 0):
            return 1
        return -1000
 
 
    def who_wins(self, s):
        """
        We can loose
 
        """
 
        if not self.is_final(s):
            return 0
        em = s
        m = em.get_missionaries()
        c = em.get_cannibals()
        if (m == 0) and (c == 0):
            return -1
        return 1
 
 
    def get_action_list(self, s):
        el = s
        loa = ActionList(el)
        nm = 0
        nc = 0
        ma_left = el.get_missionaries()
        ca_left = el.get_cannibals()
        if el.get_bank():
            nm = ma_left
            nc = ca_left
        else:
            nm = self.population - ma_left
            nc = self.population - ca_left
        ## for-while
        i = 0
        while i <= min([nm, self.boat_size]):
            ## for-while
            j = 0
            while j <= min([nc, self.boat_size - i]):
                if (i + j != 0) and i >= j or (i == 0):
                    loa.add(MissionaryAction(i, j, self.boat_size))
                j += 1
            i += 1
        return loa
 
# EOF -------------------------------------------------------------------------