Exemple #1
0
def pr2(ind):
    village = Village()
    s = '|'
    for b in ind:
        building = village.get_buildings()[b]
        building.level_up()
        s += building.get_name() + ('%02d' % building.get_level()) + "|"
    return s
Exemple #2
0
def spawn(width):
    for i in range(width):
        for j in range(width):
            new_player = Player(i * width + j, 'Jake' + str(i + 1))
            new_village = Village(new_player.name, i, j)
            new_player.villages += [new_village]
            players[new_player.id] = new_player
Exemple #3
0
def test_accumulate_susceptibles():

    v1 = Village(loc=(0.2, 0.3),
                 N=100,
                 vaccinated_fraction=0.2,
                 neighbors=set())

    v1.S = 0  # start from transiently low susceptibles
    n_generations = 26 * 300

    S_timeseries = []
    for t in range(n_generations):
        v1.update()
        S_timeseries.append(v1.S)

    plt.plot(range(n_generations), S_timeseries)
Exemple #4
0
    def create_tribe(name, user, carte):
        """
        Initialise une tribe (à utiliser après la création d'un compte)

        """
        tribe = Tribe(name=name, leader=user)
        tribe.save()

        resources_initiales = Resources(
                wood=INIT_TRIBE_RESOURCES['wood'],
                food=INIT_TRIBE_RESOURCES['food'],
                silex=INIT_TRIBE_RESOURCES['silex'],
                skin=INIT_TRIBE_RESOURCES['skin']
                )

        resources_initiales.save()
        village = Village.create_village(tribe, first=True)

        inhabitants = Group.objects.create(
                position=village.position,
                village=village,
                )
        village.inhabitants = inhabitants
        for key in INIT_TRIBE_UNITS:
            new_pile = UnitStack(
                    unit_type=UnitType.objects.get(identifier__iexact=key),
                    group=inhabitants,
                    number=INIT_TRIBE_UNITS[key],
                    )
            new_pile.save()
        village.update_income()

        return tribe
Exemple #5
0
 def __init__(self, coordinates):
     self.coordinates = coordinates
     self.n_villages = constants.WORLD['n_villages4zone']
     self.villages = []
     for i in xrange(self.n_villages):
         coord = self.coordinates
         coord['village'] = i
         self.villages.append(Village(coordinates=coord))
Exemple #6
0
 def achieve_mission_found(self):
     if not self.group.resources or\
             self.group.position.village_set.count() >= NB_VILLAGES_PER_TILE\
             or self.group.resources <\
             Resources.dict_to_resources(VILLAGE_CREATION_NEEDED_RESOURCES):
         self.come_back()
         self.group.log_report(
                 type=11,
                 subject='Impossible de créer le village',
                 body='Tous les emplacements de la case'
                     ' sélectionnée sont occupés ou bien '
                     'vous ne disposez pas de suffisamment de ressources',
                 )
     v = Village(
             name="New village",
             inhabitants=self.group,
             resources=Resources.objects.create(),
             tribe=self.group.village.tribe,
             position=self.group.position,
             )
     v.resources.save()
     v.save()
     v.update_income()
     self.group.village = v
     self.group.save()
     update_resources = v.receive_resources(self.group.resources)
     update_resources.save()
     self.group.resources = update_resources
     self.group.resources -= v.receive_resources(self.group.ressources)
     self.group.resources.save()
 def __init__(self, config):
     
     self.resources = Resources()
     self.Village = Village()
     
     self.parser = TravianParser()
     self.tclient = TravianClient(config)
     
     self.conn = False
Exemple #8
0
def test_transmit_infections():

    v0 = Village(loc=(0.2, 0.3),
                 N=10,
                 vaccinated_fraction=0.5,
                 neighbors=set())

    v0.challenge(2)

    generation = 0
    while v0.S > 0 and v0.infecteds:
        print('\n=========\ngeneration-%d\n=========' % generation)
        v0.update()
        v0.transmit()
        print(v0.summary())
        generation += 1
class TestVillage(unittest.TestCase):
    def setUp(self):
        self.world = 'pl100'
        self.village = Village(self.world)

    def test_build_normal_building(self):
        next_building = Building(self.world, 'main', 1)
        self.village.build(next_building)
        self.assertEqual(-90, self.village.wood)
        self.assertEqual(-80, self.village.stone)
        self.assertEqual(-70, self.village.iron)
        self.assertEqual(25, self.village.population)
        self.assertEqual(205, self.village.max_population)
        self.assertEqual(813, self.village.capacity)
        self.assertEqual(1, self.village.buildings['main'].level)
        self.assertEqual(10, self.village.points)

    def test_build_farm(self):
        next_building = Building(self.world, 'storage', 1)
        self.village.build(next_building)
        self.assertEqual(205, self.village.max_population)
        self.assertEqual(1000, self.village.capacity)
        self.assertEqual(6, self.village.points)

    def test_build_storage(self):
        next_building = Building(self.world, 'farm', 1)
        self.village.build(next_building)
        self.assertEqual(240, self.village.max_population)
        self.assertEqual(813, self.village.capacity)
        self.assertEqual(5, self.village.points)

    def test_add_resource(self):
        self.village.add_resource(10)
        self.assertEqual(0.07222222222222223, self.village.wood)
        self.assertEqual(0.07222222222222223, self.village.stone)
        self.assertEqual(0.07222222222222223, self.village.iron)

    def test_add_resource_max_capacity(self):
        self.village.add_resource(100000000000000)
        self.assertEqual(self.village.capacity, self.village.wood)
        self.assertEqual(self.village.capacity, self.village.stone)
        self.assertEqual(self.village.capacity, self.village.iron)
Exemple #10
0
    def __init__(self):
        self.menu = """
        Меню:
            1) Показать общую статистику о деревне
            2) Следующий день
            3) Изменить погоду
            4) Закончить игру
        """

        self.day = 1

        self.village = Village()
        self.player = Player()
        self.nature = Nature()
        self.world = World()
        self.world.add_nature(self.nature)
        self.world.add_player(self.player)
        self.village.add_player(self.player)

        for i in range(5):
            house = House()
            self.village.add_house(house)

        index = 1
        start_specialization = specialization
        list_spec = []
        for house in self.village.houses:
            for i in range(2):
                human = Human()
                spec = random.choice(start_specialization)
                list_spec.append(spec)
                if list_spec.count(spec) >= 4:
                    start_specialization.remove(spec)

                human.specialization = spec
                index += 1
                house.add_people(human)

        self.world.add_worker(self.village.get_people())
Exemple #11
0
 def setup_agents(self):
     """
     Creates a village, adds land to its territory and records
     its start date.
     """
     village = Village(self, **self.params)
     self.agents[village._id] = village
     self.grid[village.coords]['agent'] = village._id
     village.claim_land(village.coords)
     village.record_date()
Exemple #12
0
def obtainTableRows(html):
    table = html('table')[1]  # Cojo la tabla con los datos (la 0 tiene el formulario de envío)
    tableRows = table('tr')
    print(len(tableRows))
    villages = []

    for row in tableRows[1:2]:
        cells = row('td')
        # Regex para sacar coordenadas
        coords = re.findall('showOpenTipCity\((-?\d*),(-?\d*),this\)', str(cells[1]))
        coordX = coords[0][0]
        coordY = coords[0][1]

        timeCell = str(cells[9])  # la celda 9 tiene la info del viaje
        time = timeCell[4:len(timeCell) - 5]
        villages.append(Village(coordX, coordY, time))
    return villages
Exemple #13
0
    def __init__(self,
                 build_template,
                 village=None,
                 supply_resources=False,
                 world='pl100',
                 target_resources=(0, 0, 0)):
        self.build_template = build_template[:]
        self.village = village or Village(world)
        self.supply_resources = supply_resources
        self.world = world
        self.target_wood, self.target_stone, self.target_iron = target_resources

        self.build_time = 0
        self.need_wood, self.need_stone, self.need_iron = 0, 0, 0
        self.template = []
        self.generate_build_time()
        self.verbose_build_time = datetime.datetime.now() - datetime.timedelta(
            seconds=self.build_time)
Exemple #14
0
 def __init__(self):
     self.drag = False
     self.done = False
     self.game_map = GameMap()
     generate_rivers(self.game_map)
     map_width = game_map.MAP_WIDTH * game_map.SQUARE_WIDTH
     map_height = game_map.MAP_HEIGHT * game_map.SQUARE_HEIGHT
     generate_swamp(self.game_map, Point(random.randint(0, map_width), random.randint(0, map_height)), random.randint(0, 30))
     self.place_center()
     self.place_resources()
     self.old_dx = 0
     self.old_dy = 0
     self.dx = -(300 - 32 * self.center.x)
     self.dy = -(300 - 32 * self.center.y)
     self.scroll_spd_x, self.scroll_spd_y = 0, 0
     self.exp_pos = None
     self.village = Village()
     self.expeditions = []
     self.turn = 0
     self.place_monsters()
     self.specialists = [Specialist(specialist.CHIEFTAIN)]
     self.last_time = time.time() * 1000
     self.accum = 0
Exemple #15
0
def test_transmit_neighbors():

    v0 = Village(loc=(0.2, 0.3), N=10, vaccinated_fraction=0.5)

    v1 = Village(loc=(0.2, 0.3), N=10, vaccinated_fraction=0.5)

    v0.neighbors = [v1]  # only v0-towards-v1 transmissions between villages

    v0.challenge(2)

    generation = 0
    while (v0.S + v1.S) > 0 and (v0.infecteds or v1.infecteds):
        print('\n=========\ngeneration-%d\n=========' % generation)

        for v in (v0, v1):
            v.update()

        for v in (v0, v1):
            v.transmit()
            print(v.summary())

        print('=========')

        generation += 1
Exemple #16
0
    def run(self, plot_file=None):
        """
        GA repeatedly creates a village, runs it with values, then judges its
        performance and modifies values.
        Runs in groups of 10 villages.
        """
        gen = 0
        total_results = []
        P = self.init_P
        printing = False

        villages_per_gen = 30
        num_families = 10
        max_gens = 100
        max_fitness = 500
        use_ga = True
        elitism = True
        catastrophe = False
        presentation = True
        if use_ga:
            suptitle = 'Village evolution with GA'
        else:
            suptitle = 'Village evolution without GA'
        if catastrophe:
            suptitle += ' and with catastrophes'

        if presentation:
            fig = plt.figure(figsize=(8, 6), dpi=150,)
        else:
            fig = plt.figure(figsize=(12, 10), dpi=200,)
        ax = fig.add_subplot(111, aspect='auto')
        ax.set_xlabel('Generation')
        ax.set_ylabel('village trial')

        # FOR LIGHT PLOT
        #fig.suptitle(suptitle, fontsize=14, fontweight='bold')
        #cmap = 'GnBu'
        #facecolor = 'white'
        #fontcolor = 'black'

        # FOR DARK PLOT
        fig.set_facecolor('black')
        ax.set_axis_bgcolor('white')
        fig.suptitle(suptitle, fontsize=14, fontweight='bold', color='white')
        ax.spines['bottom'].set_color('gray')
        ax.spines['top'].set_color('gray')
        ax.spines['left'].set_color('gray')
        ax.spines['right'].set_color('gray')
        xa = ax.xaxis
        xa.set_tick_params(labelcolor='white')
        xa.label.set_color('white')
        ya = ax.yaxis
        ya.set_tick_params(labelcolor='white')
        ya.label.set_color('white')
        cmap='gist_earth'
        facecolor = 'black'
        fontcolor = 'white'
        if presentation:
            cmap = 'gist_ncar'

        fitness_array = np.zeros([villages_per_gen, max_gens])
        fit_plot = plt.imshow(fitness_array, interpolation='nearest',
                                cmap=cmap, origin='lower', vmin=0, vmax=max_fitness)
        ax.set_aspect('auto')
        cbar = plt.colorbar(fit_plot)
        cbytick_obj = plt.getp(cbar.ax.axes, 'yticklabels')
        plt.setp(cbytick_obj, color=fontcolor)

        # BEGIN EVOLUTION
        while gen < max_gens:
            results = []
            vill = None
            fitness = None
            print gen

            # RUN ONE VILLAGE FOR EACH GENOME
            P_index = 0
            for prof_designations in P:
                vill = Village(num_families, prof_designations)
                fitness = vill.run_village(max_fitness, printing,
                        catastrophe, presentation)
                #fitness, count_villagers, count_fams = 1, 2, 3
                results.append((fitness, prof_designations))
                vill = None

                # animation
                #curr_village = P.index(prof_designations)
                fitness_array[P_index][gen] = fitness
                #print 'f %s: %s' % (P_index, fitness)
                if presentation and P_index % 10 == 0:
                    fit_plot = plt.imshow(fitness_array, interpolation='nearest',
                                            cmap=cmap, origin='lower', vmin=0, vmax=400)
                    ax.set_aspect('auto')
                    plt.draw()
                    plt.show(block=False)
                P_index += 1

            # append set of 10 results to main set of results
            total_results.append(results)
            fit_plot = plt.imshow(fitness_array, interpolation='nearest',
                                    cmap=cmap, origin='lower', vmin=0, vmax=400)
            ax.set_aspect('auto')

            if elitism:
                fitnesses = [run[0] for run in results]
                indexes = range(len(P))
                max_fit_index = fitnesses.index(max(fitnesses))
                best_genome = P[max_fit_index][:]
            else:
                best_genome = None

            if use_ga:
                P = self.tournament_select(P, results, elitism, best_genome)
                #P = self.mutate(P, elitism, best_genome)
                #P = self.mutate_blocks(P, elitism, best_genome)
                P = self.mutate_elems(P, elitism, best_genome)
                P = self.alternate_crossover(P, elitism, best_genome)
                #P = self.three_point_crossover(P)

            else:
                # BASE: replace P with random vals
                P = []
                for x in range(villages_per_gen):
                    P.append(self.generate_genome())

            gen += 1

        plt.savefig(plot_file, bbox_inches=0, facecolor=facecolor)
        return total_results
class TravianLogic:
    
    def __init__(self, config):
        
        self.resources = Resources()
        self.Village = Village()
        
        self.parser = TravianParser()
        self.tclient = TravianClient(config)
        
        self.conn = False
        
    def connect(self):
        self.conn = self.tclient.login()
        
        return self.conn

    def update(self):
        if not self.conn:
            return False
        
        # FIELDS
        html = self.tclient.get("dorf1.php")
        dorf1 = self.parser.parse(html)
        
        # VILLAGE BUILDINGS
        html = self.tclient.get("dorf2.php")
        dorf2 = self.parser.parse(html)
        
        # PROFILE
        uid = self.parser.getProfileUid(dorf1)
        html = self.tclient.get("spieler.php?uid=%s" % (uid))
        profile = self.parser.parse(html) 
        
        ### RALLY POINT
        html = self.tclient.get("build.php?id=39")
        rally_point = self.parser.parse(html)
            
        
        village_name = self.parser.getVillageName(dorf1)
        server_time, calculated = self.parser.getServerTime(dorf1)
        
        res = self.parser.getRes(dorf1)
        troops = self.parser.getTroops(dorf1)
        movements = self.parser.getMovements(dorf1)
        
        
        fields = self.parser.getFields(dorf1)
        for field in fields:
            id, name, level = field
            self.Village.updateBuilding(id, name=name, level=level)            
        
        buildings = self.parser.getVillageBuildings(dorf2)
        for build in buildings:
            id, name, level = build
            self.Village.updateBuilding(id, name=name, level=level)
        
        villages = self.parser.getVillages(profile)
        

        
        print self.Village

        mega_troop = Troop()
        mega_troop.owner = "angelow"        
        
        my, reinf, prisoners = self.parser.getRallyPoint(rally_point)
        for village, troops in my.items():
            t = Troop()
            t.village = village
            t.owner = "myself"
            
            t.update(troops)
            print t
            mega_troop += t
            
        for owner, data in reinf.items():
            for village, troops in data.items():
                t = Troop()
                t.village = village
                t.owner = owner
                t.type = "deff"
                t.update(troops)

                
                print t                
                mega_troop += t
            
        for owner, data in prisoners.items():
            for village, troops in data.items():
                t = Troop()
                t.village = village
                t.owner = owner
                t.type = "prisoners"
                t.update(troops)

                print t          
                mega_troop += t
        
        mega_troop.owner = "angelow"
        mega_troop.village = village_name
        mega_troop.type = "all units"
        print mega_troop
        

        
        
            

        
        
        
        
        return True        
 def setUp(self):
     self.world = 'pl100'
     self.village = Village(self.world)
Exemple #19
0
from population import Population
from village import Village
from compute import list_add
from flask import Flask, request, render_template, Blueprint, send_from_directory
from config import DevConfig
import json
from jinja2 import Template

profile = Blueprint('opendata_final', __name__)

p = Population()
v = Village()


def multiply_population_data(population_data, proportion):
    result = dict()
    result["household_no"] = population_data["household_no"] * proportion
    result["people_total"] = population_data["people_total"] * proportion
    result["people_total_m"] = population_data["people_total_m"] * proportion
    result["people_total_f"] = population_data["people_total_f"] * proportion
    result["people_m"] = [t * proportion for t in population_data["people_m"]]
    result["people_f"] = [t * proportion for t in population_data["people_f"]]
    return result


def add_population_data(population_data1, population_data2):
    if population_data1 == {}:
        return population_data2
    else:
        result = dict()
        result["household_no"] = population_data1[
Exemple #20
0
    @listen_to('build')
    def on_build(self, event):
        if len(self.village.get_build_events_for_slot(self.slot_id)) == 0:
            self.terminate()
            self.callback()
        
if __name__ == '__main__':
    from village import Village
    from account import Account
    from resources import Resources
    from event import Event
    
    class K():
        @trigger(TriggerEnoughSpaceForResources)
        def handler_enought_space(self):
            print("enough!")
        
    vill = Village(Account((0,0), None), None, None, None)
    vill.resources = Resources((90,0,0,0))
    vill.storage_capacity = Resources((100,0,0,0))
    vill.next_refresh_time = datetime(2220, 1, 1)
    
    inst = K()
    inst.handler_enought_space().enqueue(vill, Resources((20,0,0,0)))
    print("first check")
    vill.fire_event(Event(vill, 'spend_resources', datetime.now()))
    print("second check")
    vill.resources = Resources((0,0,0,0))
    vill.fire_event(Event(vill, 'spend_resources', datetime.now()))
    print(vill.triggers)
    
Exemple #21
0
class Simulation:
    time = 0
    wait = 0
    res = [0, 0, 0]
    points = 0
    queue = []
    village = 0

    def __init__(self):
        self.village = Village()

    def consume_resources(self, cost):
        for i in range(len(self.res)):
            self.res[i] -= cost[i]

    def calc_time(self, dt, w=False):
        self.time += dt
        if w:
            self.wait += dt
        capacity = self.village.get_capacity()
        for i in range(len(self.res)):
            self.res[i] = min(
                [capacity, self.res[i] + self.village.get_yield(i) * dt])

    def get_time(self):
        return self.time / 3600.0 / 24.0

    def get_wait(self):
        return self.wait

    def has_resources(self, target):
        return self.res[0] >= target[0] and self.res[1] >= target[
            0] and self.res[2] >= target[2]

    def has_population(self, target):
        return self.village.get_population() <= self.village.get_pop_limit()

    def build(self, item):
        next_from_queue = self.village.get_buildings()[item]
        if next_from_queue.get_level() >= next_from_queue.get_max_level():
            print "tried raise " + str(item) + " to level " + str(
                next_from_queue.get_level())
            return False
        next_cost = next_from_queue.get_cost()
        if max(next_cost) > self.village.get_capacity():
            # print "res fail", next_cost, self.village.getCapacity()
            return False
        if not self.has_resources(next_cost):
            max_time = 0
            for i in range(len(self.res)):
                diff = next_cost[i] - self.res[i]
                prod = self.village.get_yield(i)
                t = diff / prod
                if t > max_time:
                    max_time = t
            self.calc_time(max_time, True)
        self.consume_resources(next_cost)
        base_time = next_from_queue.get_build_time()
        dt = base_time * 1.05**(-self.village.hq.get_level())
        self.calc_time(dt)
        next_from_queue.level_up()
        if not self.has_population(next_cost):
            # print "pop fail", self.village.getPopulation(), self.village.getPopLimit(), next_from_queue().getLevel()
            return False
        self.points = sum(
            map(lambda b: b.get_points(), self.village.get_buildings()))
        return True

    def simulate(self, q):
        for item in q:
            if not self.build(item):
                self.calc_time(float('inf'), True)
                # self.calcTime(365 * 24 * 60 * 60, True)
                break
        return -self.get_time(), self.points  # , -self.getWait()
Exemple #22
0
 def __init__(self):
     self.village = Village()
Exemple #23
0
class CreateCharacter(StateHandler):
    def __init__(self, gamedata):
        StateHandler.__init__(self, CreateCharacter.start, [
            CreateCharacter.start, CreateCharacter.ask,
            CreateCharacter.strength, CreateCharacter.agility,
            CreateCharacter.speed, CreateCharacter.defense,
            CreateCharacter.confirm, CreateCharacter.store
        ], Quit(), gamedata)


CreateCharacter.start = Start()
CreateCharacter.ask = Ask()
CreateCharacter.strength = Strength()
CreateCharacter.agility = Agility()
CreateCharacter.speed = Speed()
CreateCharacter.defense = Defense()
CreateCharacter.confirm = Confirm()
CreateCharacter.store = Store()

if __name__ == '__main__':
    gamedata = GameData()
    player = Player()
    gamedata.player = player
    util.create_player_file(gamedata)
    gamedata.player = util.load_player("player.json")
    create_char = CreateCharacter(gamedata)
    create_char_gd = create_char.run()
    village = Village(create_char_gd)
    village_gd = village.run()
Exemple #24
0
    def go(self):

        """ run one turn of the simulation. """

        self.state.people = list(setup_people(self.state,self.coeffs,self.tc))
        self.village = Village(self.state,self.coeffs,self.tc)

        # only run if they're already alive
        if self.is_game_over():
            return (False,self.state)

        self.reset()

        # allocate calories
        if not self.state.subsistence_met:
            self.buy_food()
            

        # buy and sell goods in the village market
        self.sell_items()
        self.purchase_items()
        
        self.doctor()
        self.pregnancy()
        self.education()

        self.state.maximum_effort = self.calc_maximum_effort()

        self.check_sick()

        # village-wide updates
        self.village.buy_improvements()
        self.free_bednets()

        self.village.update_precipitation()
        self.check_drought()

        self.village.update_population()
        self.village.check_epidemic()

        self.update_population_count()
        self.update_yield()
        self.update_subsistence()

        self.check_final_health()

        # And now we'll figure out whether subsistence was met for the *next* season
        # We have to do this after check_final_health in case someone died there
        if self.is_subsistence_met():
            self.state.subsistence_met = True
        else:
            self.state.subsistence_met = False

            if not self.cooker.was_sufficient:
                # TODO finer-grained messages about fuel usage
                # (e.g. if not enough propane, but was augmented with collected wood to meet req.)
                if self.cooker.raw_leftovers == 0:
                    self.message("insufficient food")  # TODO there's no user-facing message for this one
                elif 'stove' in self.state.owned_items:
                    self.message("insufficient propane")
                else:
                    self.message("insufficient wood")

        self.state.maximum_effort = self.calc_maximum_effort()
        self.update_finances()

        self.age_people()
        self.increment_time()
        self.age_bednets()
        self.update_population_count()

        # update state with changes to people
        self.state = marshall_people(self.state.people,self.state)

        self.state.total_effort = sum(self.state.efforts)
        self.update_points()
        self.state.try_for_child = False
        self.village.update_subsidy_offers()
        self.state.food_to_buy = 0
        if self.is_game_over():
            return (False,self.state)
        return (True,self.state)
Exemple #25
0
        action='store_true',
        help="Create a player save file. Stored to player.json by default")

    parser.set_defaults(create_player=False)
    args = parser.parse_args()

    # create gamedata object that holds game information
    gamedata = GameData()

    if args.savefile is not None:
        if args.b:
            gamedata.b = True
        else:
            gamedata.b = False
        gamedata.player = util.load_player(args.savefile)
        vil = Village(gamedata)
        vil_gd = vil.run()
    elif args.b is True:
        gamedata.b = True
        gamedata.player = Player()
        util.create_player_file(gamedata)
        char = CreateCharacter(gamedata)
        gd = char.run()
        vil = Village(gd)
        gd_vil = vil.run()
    else:
        if args.b is True:
            gamedata.b = True
        else:
            gamedata.b = False
        gamedata.b = False
Exemple #26
0
class Turn:
    def __init__(self,state,coeffs,tc):
        self.state  = state
        self.coeffs = coeffs
        self.tc     = tc
        #self.update_bank_offer()
        # TODO: I do not know why this does not work.
        #if self.state.year == -1:
           #self.state.year = self.coeffs.starting_year

    def calc_maximum_effort(self):
        return sum([p.maximum_effort() for p in self.state.people]) - self.calc_school_effort()

    def reset(self):
        self.state.expenditure         = 0
        self.state.tons_to_market      = 0
        self.state.income              = 0
        self.state.initial_population  = self.state.population
        self.state.total_effort        = sum(self.state.efforts)
        self.state.fertilizer          = False
        self.state.high_yield_seeds    = False
        self.state.user_messages       = []
        self.state.died                = []
        self.state.died_reasons        = []

    def message(self,m):
        self.state.user_messages.append(m)

    def is_game_over(self):
        return self.is_everyone_dead() or self.is_debt_too_high()

    def is_everyone_dead(self):
        if self.state.population < 1:
            return True
        return False

    def is_debt_too_high(self):
        if self.state.cash < -100:
            return True
        return False

    def go(self):

        """ run one turn of the simulation. """

        self.state.people = list(setup_people(self.state,self.coeffs,self.tc))
        self.village = Village(self.state,self.coeffs,self.tc)

        # only run if they're already alive
        if self.is_game_over():
            return (False,self.state)

        self.reset()

        # allocate calories
        if not self.state.subsistence_met:
            self.buy_food()
            

        # buy and sell goods in the village market
        self.sell_items()
        self.purchase_items()
        
        self.doctor()
        self.pregnancy()
        self.education()

        self.state.maximum_effort = self.calc_maximum_effort()

        self.check_sick()

        # village-wide updates
        self.village.buy_improvements()
        self.free_bednets()

        self.village.update_precipitation()
        self.check_drought()

        self.village.update_population()
        self.village.check_epidemic()

        self.update_population_count()
        self.update_yield()
        self.update_subsistence()

        self.check_final_health()

        # And now we'll figure out whether subsistence was met for the *next* season
        # We have to do this after check_final_health in case someone died there
        if self.is_subsistence_met():
            self.state.subsistence_met = True
        else:
            self.state.subsistence_met = False

            if not self.cooker.was_sufficient:
                # TODO finer-grained messages about fuel usage
                # (e.g. if not enough propane, but was augmented with collected wood to meet req.)
                if self.cooker.raw_leftovers == 0:
                    self.message("insufficient food")  # TODO there's no user-facing message for this one
                elif 'stove' in self.state.owned_items:
                    self.message("insufficient propane")
                else:
                    self.message("insufficient wood")

        self.state.maximum_effort = self.calc_maximum_effort()
        self.update_finances()

        self.age_people()
        self.increment_time()
        self.age_bednets()
        self.update_population_count()

        # update state with changes to people
        self.state = marshall_people(self.state.people,self.state)

        self.state.total_effort = sum(self.state.efforts)
        self.update_points()
        self.state.try_for_child = False
        self.village.update_subsidy_offers()
        self.state.food_to_buy = 0
        if self.is_game_over():
            return (False,self.state)
        return (True,self.state)


    def free_bednets(self):
        if not self.coeffs.enable_free_bednets or \
           self.state.year != self.coeffs.starting_year + self.coeffs.free_bednet_year:
            # this only happens in a specific year
            return

        num_bednets = len([elem for elem in self.state.owned_items if elem == "bednet"])
        needed_bednets = self.state.population / 2
        
        if num_bednets < needed_bednets:
            #self.message("An NGO has distributed free bednets to the village and your family.")
            self.message('NGO bednets')
            self.state.owned_items.extend(['bednet'] * needed_bednets)
            self.state.bednet_ages.extend([0] * needed_bednets)


    def sell_items(self):
        # front end gives us a list of "|" seperated item,quantity pairs
        # NOTE: no validation to make sure they have the items to sell
        try:
            # just take this opportunity to keep the list clean
            self.state.owned_items.remove('')
        except:
            pass

        real_sold_items = []
        for i in self.state.sell_items:
            if i == "":
                continue
            item, quantity = i.split("|") 
            quantity = int(quantity)

            num_sold = 0
            for x in range(quantity):
                try:
                    self.state.owned_items.remove(item)
                    num_sold += 1
                except ValueError:
                    # trying to sell something we don't have
                    # or more than we have of that item
                    # eg, if they try to sell bednets on the
                    # turn that they've deteriorated and are now
                    # no longer in the owned_items
                    continue

            real_sold_items.append("%s|%s" % (item, num_sold))
            price = self.check_sell_price(item) * num_sold

            self.state.cash += price
            if item == "stove":
                self.state.stove = False
            if item == "improvedstove":
                self.state.improved_stove = False
            if item == "boat":
                self.state.boat = False
            if item == "dragnet":
                self.state.dragnet = False
        self.state.sell_items = real_sold_items

    def purchase_items(self):

        # pay for education first
        self.state.cash -= self.calc_school_cost()

        # front end gives us a list of "|" separated item,quantity pairs
        # NOTE: no validation to check if they have the money
        for i in self.state.purchase_items:
            if i == "":
                continue
            item,quantity = i.split("|")
            price = self.check_purchase_price(item) * int(quantity)
            self.state.cash -= price
            for x in range(int(quantity)):
                # some items only affect state, are not stored
                if item == "fertilizer":
                    self.state.fertilizer = True
                elif item == "propane":
                    self.state.amount_propane += 10 # 10kg propane per tank
                elif item == "high_yield_seeds":
                    self.state.high_yield_seeds = True
                else:
                    self.state.owned_items.append(item)
            if item == "bednet":
                self.state.bednet_ages.extend([0] * int(quantity))
            if item == "stove":
                self.state.stove = True
            if item == "improvedstove" or item == "improved_stove":
                self.state.improved_stove = True
            if item == "boat":
                self.state.boat = True
            if item == "dragnet":
                self.state.dragnet = True

    def food_cost(self):
        cost = self.coeffs.food_cost
        if self.state.meals:
            # school meals raise maize prices by 20%
            # TODO: should probably be a coefficient
            cost *= 1.2
        self.state.calculated_food_cost = cost
        return cost
        
    def subsistence_cost(self):
        return self.calc_family_needs() / 100 * self.food_cost()

    def buy_food(self):
        cost = self.state.food_to_buy * self.food_cost()
        self.state.cash -= cost
        self.state.amount_calories = self.state.amount_calories + (self.state.food_to_buy * 10 * 180.0)

    def check_purchase_price(self,item):
        prices = dict()
        for i,price in zip(self.coeffs.market_items,self.coeffs.market_purchase_prices):
            prices[i] = price
        multiplier = 1.0
        if self.state.road:
            multiplier = 0.8
        return multiplier * prices[item]
        
    def check_sell_price(self,item):
        prices = dict()
        for i,price in zip(self.coeffs.market_items,self.coeffs.market_sell_prices):
            prices[i] = price
        return prices[item]

    def update_points(self):
        """ calculate achievement points for the turn """

        X = 30.0
        F = 2.0

        # we don't actually keep track of what the initial village
        # population was after the first turn, so i'm hard-coding it at 1000
        # for now
        initial_num_families = 1000.0 / self.coeffs.avg_family_size
        
        D = (100.0 * X) / initial_num_families

        V = 1000000.0 / (self.village.raw_improvement_price('road') * 0.05)

        self.state.u_points += (
            (X * self.calc_family_total_health()) +
            (self.state.income) +
            (F * self.calc_new_improvements_value()) + 
            (V * self.village.calc_new_improvements_value()) + 
            (D * (self.state.village_births - self.state.village_deaths))
            )
        
        # don't let points go below 0
        self.state.u_points = int(max(self.state.u_points,0))

    def calc_family_total_health(self):
        if len(self.state.people) == 0:
            return 0
        return float(sum([p.health for p in self.state.people]))

    def calc_family_avg_health(self):
        if len(self.state.people) == 0:
            return 0
        return float(sum([p.health for p in self.state.people])) / float(len(self.state.people))

    def calc_school_effort(self):
        """ number of hours family members spent in school """
        primary   = len([p for p in self.state.people if p.in_primary_school()])
        secondary = len([p for p in self.state.people if p.in_secondary_school()])

        return (int(self.coeffs.primary_school_effort) * primary) + \
               (int(self.coeffs.secondary_school_effort) * secondary)

    def calc_school_cost(self):
        """ francs spent on education for children """
        n = len([p for p in self.state.people if p.in_secondary_school()])
        return n * self.coeffs.secondary_school_cost

    def family_improvements_count(self):
        """ count of how many family improvements have been made """
        improvements = ["bednet","improved_stove","stove","boat","dragnet"]
        return len([i for i in self.state.owned_items if i in improvements])

    def calc_new_improvements_value(self):
        value = 0
        for i in self.state.purchase_items:
            if i == "":
                continue
            item,quantity = i.split("|")
            price = self.check_purchase_price(item) * int(quantity)
            value += price
        return value

    def village_improvements_count(self):
        """ count of how many village improvements have been made """
        return self.village.improvements_count()

    def update_population_count(self):
        """ Ensure that the population count is correct """
        self.state.population = len(self.state.people)
        
    def doctor(self):
        for (p,doctor) in zip(self.state.people,self.state.doctor):
            if doctor:
                p.visit_doctor()
                cost = self.coeffs.doctor_visit_cost
                if self.state.clinic:
                    # doctor visits are 20% normal when there's a clinic
                    cost *= .2
                self.state.cash -= cost

    def get_mother(self):
        """ retrieve the "mother" """
        for p in self.state.people:
            if p.name == 'Fatou':
                return p
            
        # if we make it here, Fatou must be dead
        # return a NullPerson instead
        class NullPerson:
            pregnant = False
            def make_pregnant(self):
                pass
        return NullPerson()


    def pregnancy(self):
        if self.state.try_for_child:
            # make Fatou pregnant
            fatou = self.get_mother()
            fatou.make_pregnant()
            #if fatou.pregnant:
                #self.message("%s is now pregnant." % fatou.name)
                #self.message(('pregnant',fatou.name))


    def education(self):
        for (p,enroll) in zip(self.state.people,self.state.enroll):
            p.update_schooling_state(enroll=enroll) 
            p.update_education()

    def children(self):
        """ have children, if any """
        if self.state.try_for_child:
            return False
        fatou = self.get_mother()
        baby = None
        if fatou.pregnant:
            baby = new_child(self.tc,self.coeffs,self.state)
            self.message('child born')
            self.state.people.append(baby)
            fatou.pregnant = False
            
            # maternal mortality check
            maternal_mortality_probability = 5
            if self.state.clinic:
                maternal_mortality_probability = 1
            # do it as greater than 100 - probability instead of
            # < probability because of the way rand_n() is stubbed out
            # in the unit tests to always return the lowest value
            if self.rand_n(100) > (100 - maternal_mortality_probability):
                self.state.died.append(fatou.name)
                self.state.died_reasons.append("childbirth")
                self.state.deaths += 1
                self.state.people.remove(fatou)
        self.update_population_count()
        if baby is not None:
            return True
        return False

    def update_finances(self):
        """ calculate the family's finances """
        self.determine_income()
        family_income_and_interest = self.income_plus_interest(self.state.income)

        taxes = self.village.family_taxes(family_income_and_interest)

        self.state.cash = self.determine_cash(self.state.income, self.state.cash, taxes)

        self.village.collect_taxes(taxes)

    def income_plus_interest(self,income):
        return max(float((float(income) * float(1.0 + self.coeffs.savings_rate))),0.0)

    def determine_cash(self,income,cash,taxes):
        if income < 0:
            return cash + income
        else:
            return cash + self.income_plus_interest(income) - taxes

    def increment_time(self):
        if self.state.season:
            self.state.year += 1
            self.state.season = False
        else:
            self.state.season = True

    def age_people(self):
        # TODO: subtly broken for children born in the wrong season
        if self.state.season:
            for p in self.state.people:
                p.age += 1

    def age_bednets(self):
        if 'bednet' not in self.state.owned_items:
            self.state.bednet_ages = []
            return
        try:
            self.state.bednet_ages.remove('')
        except:
            pass
        # age them
        self.state.bednet_ages = [age + 1 for age in self.state.bednet_ages]
        # if any are more than 5 years (10 turns)
        # we eliminate them
        to_remove = []
        for age in self.state.bednet_ages:
            if age > 9:
                try:
                    self.state.owned_items.remove('bednet')
                except ValueError:
                    # something weird.
                    pass
                to_remove.append(age)
                self.message('bednet deteriorated')
        for age in to_remove:
            try:
                self.state.bednet_ages.remove(age)
            except ValueError:
                pass

    def check_drought(self):
        self.state.drought = False

        # if there's irrigation, we have no drought
        if self.state.irrigation:
            return
        
        # anything less than the threshold is considered a drought
        if self.state.precipitation < self.coeffs.drought_threshold:
            self.state.drought = True

    def rand_n(self,n):
        return self.tc.randint(a=0,b=n,n=1).values[0]

    def check_final_health(self):
        dead = []
        for person in self.state.people:
            if person.is_dead():
                dead.append(person)
                self.state.died.append(person.name)
                self.state.died_reasons.append('unknown')   # TODO reason for death
        for d in dead:
            self.state.people.remove(d)
        self.state.deaths += len(dead)
        self.update_population_count()

    def check_sick(self):
        for p in self.state.people:
            p.check_sick(self.state)
            
    def update_yield(self):
        self.update_avg_productivity()
        self.update_amount_fish()
        self.update_soil_health()
        self.update_amount_maize()
        self.update_amount_cotton()
        self.update_amount_wood()
        self.update_amount_water()
        self.update_small_business_income()
        self.update_microfinance_bank()
        self.convert_calories()
        self.village.update_fish_stock()
        self.village.update_wood_stock()

    def t_boat(self):
        if self.state.boat:
            return self.coeffs.boat_coeff
        return 1.0

    def t_dragnet(self):
        if self.state.dragnet:
            return self.coeffs.dragnet_coeff
        return 1.0

    def t_fert(self):
        if self.state.fertilizer:
            return self.coeffs.fertilizer_coeff
        return 1.0

    def t_fert_cotton(self):
        if self.state.fertilizer:
            return self.coeffs.fertilizer_cotton_coeff
        return 1.0

    def t_irr(self):
        if self.state.irrigation:
            return self.coeffs.irrigation_coeff
        return 1.0

    def t_drought(self):
        # XXX TODO: fix tight coupling with check_drought()
        if self.state.drought:
            return self.coeffs.drought_coeff
        return 1.0

    def update_soil_health(self):
        """ updates the soil health depending on whether fertilizer has been used in the last three years """
        if self.state.fertilizer or self.state.fertilizer_t1 or \
               self.state.fertilizer_t2:
            self.state.soil_health = 1.0
        else:
            #self.message("Soil health is depleted.")
            self.state.soil_health = self.coeffs.soil_depletion
            
        if self.state.season:
            # once a year, rotate fertilizer history
            self.state.fertilizer_t2 = self.state.fertilizer_t1
            self.state.fertilizer_t1 = self.state.fertilizer or self.state.fertilizer_last_turn
        else:
            # it gets a little weird since we only care about the fertilizer
            # history per year, but it's a user option on each turn
            # so we use fertilizer_last_turn to fill in the gap
            self.state.fertilizer_last_turn = self.state.fertilizer

    def calc_amount_fish(self):
        assert self.state.effort_fishing >= 0
        assert self.coeffs.avg_fishing_yield >= 0
        assert self.state.avg_productivity >= 0
        assert self.t_boat() >= 0
        assert self.t_dragnet() >= 0
        assert self.state.fish_coeff >= 0
        return self.coeffs.fishing_effort_coeff * self.state.effort_fishing \
            * self.coeffs.avg_fishing_yield \
            * ((95.0 + self.rand_n(10)) / 100.0) \
            * self.state.avg_productivity * self.t_boat() \
            * self.t_dragnet() \
            * self.state.fish_coeff

    def update_amount_fish(self):
        self.update_fish_coeff()
        self.state.amount_fish = self.calc_amount_fish()
        if self.state.fishing_limit > 0 :
            self.state.amount_fish = min(self.state.fishing_limit,
                                         self.state.amount_fish)

    def calc_wood_coeff(self):
        if self.state.wood_stock >= self.coeffs.wood_k / 2.0:
            return 1
        else:
            assert self.coeffs.wood_k != 0
            return self.state.wood_stock / self.coeffs.wood_k

    def update_wood_coeff(self):
        # TODO: does wood_coeff actually need to be a state variable?
        self.state.wood_coeff = self.calc_wood_coeff()

    def calc_fish_coeff(self):
        if self.state.fish_stock < 0:
            self.state.fish_stock = 0
        if self.state.fish_stock >= self.coeffs.fish_k / 2.0:
            return 1.0
        else:
            assert self.coeffs.fish_k != 0
            return self.state.fish_stock / self.coeffs.fish_k

    def update_fish_coeff(self):
        self.state.fish_coeff = self.calc_fish_coeff()

    def percent_maize(self):
        """ what percent of the family's fields are growing Maize """
        if len(self.state.crops) == 0:
            return 0
        n_maize = len([x for x in self.state.crops if x.lower() == 'maize'])
        return float(n_maize) / len(self.state.crops)

    def percent_cotton(self):
        """ what percent of the family's fields are growing Cotton """
        if len(self.state.crops) == 0:
            return 0
        n_cotton = len([x for x in self.state.crops if x.lower() == 'cotton'])
        return float(n_cotton) / len(self.state.crops)

    def t_high_yield_seeds(self):
        if self.state.high_yield_seeds:
            return self.coeffs.maize_high_yield_seeds_multiplier
        return 1.0

    def calc_amount_maize(self):
        assert self.coeffs.productivity_effort_coeff >= 0
        assert self.state.effort_farming >= 0
        assert self.coeffs.avg_maize_yield >= 0
        assert self.state.avg_productivity >= 0
        assert self.state.soil_health >= 0
        assert self.t_fert() >= 0
        assert self.t_irr() >= 0
        assert self.t_high_yield_seeds() >= 0
        assert self.percent_maize() >= 0 and self.percent_maize() <= 1.0
        return max((
                ((self.coeffs.productivity_effort_coeff * self.state.effort_farming) ** self.coeffs.maize_productivity_exponent)
                * self.coeffs.avg_maize_yield
                * ((95.0 + self.rand_n(10)) / 100.0)
                * self.state.avg_productivity
                * self.t_drought() * self.t_irr()
                * self.state.soil_health * self.t_fert()
                * self.t_high_yield_seeds()
                * self.percent_maize())
                   , 0.0)
    
    def calc_amount_cotton(self):
        return max(((self.coeffs.productivity_effort_coeff * self.state.effort_farming) ** self.coeffs.cotton_productivity_exponent) \
                       * self.coeffs.avg_cotton_yield \
                       * ((95.0 + self.rand_n(10)) / 100.0) \
                       * self.state.avg_productivity \
                       * self.state.soil_health * self.t_fert_cotton() \
                       * self.t_drought() * self.t_irr() \
                       * self.percent_cotton()
                   , 0.0)

    def update_amount_cotton(self):
        self.state.amount_cotton = self.calc_amount_cotton()
        assert self.state.amount_cotton >= 0
        # update user messages
        if self.state.amount_cotton > 1:
            self.message('good cotton')
    
    def update_amount_maize(self):
        self.state.amount_maize = self.calc_amount_maize()
        assert self.state.amount_maize >= 0
        # update user messages
        if self.state.amount_maize > 0:
            if self.state.amount_maize < 1:
                self.message('poor maize')
        if self.state.amount_maize > 3:
            self.message('good maize')

    def calc_amount_wood(self):
        return self.coeffs.wood_effort_coeff * self.state.effort_fuel_wood \
            * self.coeffs.avg_wood_yield \
            * ((95.0 + self.rand_n(10)) / 100.0) \
            * self.state.avg_productivity * self.calc_wood_coeff()

    def update_amount_wood(self):
        self.state.amount_wood = self.calc_amount_wood()
        if self.state.wood_limit > 0 and \
                self.state.amount_wood > self.state.wood_limit:
            self.state.amount_wood = self.state.wood_limit
        assert self.state.amount_wood >= 0

    def calc_amount_water(self):
        return self.state.effort_water \
            * self.coeffs.avg_water_yield \
            * ((95.0 + self.rand_n(10)) / 100.0) \
            * self.calc_family_avg_health()

    def update_amount_water(self):
        self.state.amount_water = self.calc_amount_water()
        assert self.state.amount_water >= 0
        
    def calc_small_business_capital(self):
        return (1 - self.coeffs.small_business_depreciation_rate) * self.state.small_business_capital + self.state.small_business_investment

    def calc_small_business_income(self):
        # update capital, accounting for depreciation
        self.state.small_business_capital = self.calc_small_business_capital()
        self.state.cash -= self.state.small_business_investment
    
        assert self.state.effort_small_business >= 0
        assert self.state.small_business_capital >= 0
        #return self.state.effort_small_business \
        #       * self.coeffs.avg_small_business_yield \
        #       * ((95.0 + self.rand_n(10)) / 100.0) \
        #       * self.state.avg_productivity

        return self.coeffs.small_business_productivity_effect * \
            ( ((self.state.avg_productivity * self.state.effort_small_business) ** self.coeffs.small_business_diminishing_return) * \
                  (self.state.small_business_capital ** (1 - self.coeffs.small_business_diminishing_return)) \
                  ) * \
                  (1 + (self.coeffs.small_business_road_effect * self.state.road)) * \
                  (1 + (self.coeffs.small_business_electricity_effect * self.state.electricity)) * \
                  (self.coeffs.small_business_drought_effect * ((self.state.precipitation / self.coeffs.avg_precipitation) ** 0.4) ) * \
                  (self.coeffs.small_business_epidemic_effect * (1 - self.state.epidemic))

    def update_small_business_income(self):
        self.state.small_business_income = self.calc_small_business_income()
        assert self.state.small_business_income >= 0

    def calc_microfinance_max_borrow(self):
        return self.subsistence_cost() + self.state.small_business_capital
        
    def pay_microfinance_bank(self):
        # first from family fund, then business capital, then carryover
        amount_due = self.state.microfinance_amount_due
        amount_paid = 0.0
        if self.state.cash >= amount_due:
            self.state.cash -= amount_due
            amount_paid += amount_due
        elif self.state.cash < 0:
            amount_paid = 0.0
        else:
            amount_paid = self.state.cash
            self.state.cash = 0

        remaining_due = amount_due - amount_paid
        if self.state.small_business_capital >= remaining_due:
            self.state.small_business_capital -= remaining_due
            amount_paid += remaining_due
        else:
            amount_paid += self.state.small_business_capital
            self.state.small_business_capital = 0

        self.state.microfinance_balance -= amount_paid

        # save carryovers if we couldn't pay it all
        self.state.microfinance_amount_paid = amount_paid
        self.state.microfinance_amount_due -= amount_paid

        if self.state.microfinance_balance < 0:
            self.state.microfinance_balance = 0.0

        return

    def calc_microfinance_balance(self):
        interest = self.state.microfinance_balance * self.state.microfinance_interest_rate / 100

        self.state.microfinance_balance += interest
        payment_amount = self.state.microfinance_borrow / self.coeffs.microfinance_repay_period

        # add any amount carried over from the previous turn
        if self.state.microfinance_balance > payment_amount:
            self.state.microfinance_amount_due += payment_amount + interest
        else:
            self.state.microfinance_amount_due += self.state.microfinance_balance

        # now actually pay
        self.pay_microfinance_bank()
        return self.state.microfinance_balance

    def calc_microfinance_interest(self):
        return (self.coeffs.microfinance_base_interest * ((100.0 + self.rand_n(10)) / 100.0) \
                    + (self.coeffs.microfinance_drought_effect * (self.state.precipitation / self.coeffs.avg_precipitation)) \
                    + (self.coeffs.microfinance_epidemic_effect * self.state.epidemic))

    def update_microfinance_interest(self):
        self.state.microfinance_current_interest_rate = self.calc_microfinance_interest()

    def update_microfinance_bank(self):
        self.state.microfinance_amount_paid = 0
        if self.state.microfinance_balance == 0:
            self.state.microfinance_amount_due = 0
            if self.state.microfinance_borrow > 0:
                # new loan
                if self.state.microfinance_borrow > self.state.microfinance_max_borrow:
                    self.state.microfinance_borrow = self.state.microfinance_max_borrow
                self.state.microfinance_balance = self.state.microfinance_borrow
                self.state.cash += self.state.microfinance_borrow
            self.state.microfinance_interest_rate = \
                self.state.microfinance_current_interest_rate
        else:
            self.state.microfinance_balance = self.calc_microfinance_balance()

        # update loan offer
        self.update_bank_offer()
 

    def update_bank_offer(self):        # update loan offer
        self.state.microfinance_max_borrow = self.calc_microfinance_max_borrow()
        self.update_microfinance_interest()


    def convert_calories(self):
        assert self.state.amount_maize >= 0
        assert self.state.amount_fish >= 0
        assert self.coeffs.maize_cal_coeff >= 0
        assert self.coeffs.fish_cal_coeff >= 0
        self.state.maize_cals = self.state.amount_maize * self.coeffs.maize_cal_coeff
        self.state.fish_cals  = self.state.amount_fish  * self.coeffs.fish_cal_coeff
        assert self.state.maize_cals >= 0
        assert self.state.fish_cals >= 0

    @property
    def cooker(self):
        assert hasattr(self, '_cooker'), "You must first call new_cooker"
        return self._cooker

    def new_cooker(self):
        self._cooker = fuel.FuelSupply(self.coeffs, self.state)
        return self._cooker

    def calc_amount_calories(self):
        raw_food_cals = self.state.maize_cals + self.state.fish_cals
        cooker = self.new_cooker()
        cooked = cooker.convert(raw_food_cals)
        return cooked + self.school_meal_calories()

    def school_meal_calories(self):
        if not self.state.meals:
            return 0

        enrolled_children = len([p for p in self.state.people if
                                 p.schooling_state.startswith('enrolled')])
        return self.coeffs.school_meals_calories * enrolled_children


    def update_amount_calories(self):
        self.state.amount_calories = self.calc_amount_calories()

    def is_subsistence_met(self):
        return self.state.amount_calories >= self.calc_family_needs()

    def is_water_subsistence_met(self):
        return self.state.amount_water >= self.state.family_water_needs

    def calc_family_needs(self):
        return stateless_logic.family_food_requirements(
            self.state.population,
            self.coeffs.subsistence)

    def update_family_needs(self):
        self.state.family_needs = self.calc_family_needs()

    def calc_family_water_needs(self):
        return self.state.population * self.coeffs.w_subsistence

    def update_family_water_needs(self):
        self.state.family_water_needs = self.calc_family_water_needs()

    def update_subsistence(self):
        self.update_family_needs()
        self.update_family_water_needs()

        # first update family health based on stored food from last season
        if self.is_subsistence_met():
            for p in self.state.people:
                p.update_health(self.coeffs.subsistence,
                                self.state.clinic,
                                self.state.electricity)
                #p.increment_health(self.coeffs.health_increment)
        else:
            for p, daily_calories in zip(self.state.people, self.state.calorie_allocation):
                calories = daily_calories * 180
                p.update_health(calories, self.state.clinic, self.state.electricity)

        # now that we've figured out whether we had enough food stored 
        # for subsistence this *past* season, we need to have any new
        # children we're gonna have -- so that we can then figure out
        # whether we'll have enough food stored for subsistence *next*
        # season -- so that we can warn the player and give him a chance
        # to purchase extra needed food and/or allocate available calories
        new_children = self.children()
        if new_children:
            self.update_family_needs()
            self.update_family_water_needs()


        # now we'll update the stored calories based on our newly farmed fish & grain
        self.update_amount_calories()

        self.state.food_to_sell = self.cooker.raw_leftovers

        propane_remaining = self.cooker.stock('propane')
        self.state.report_propane_used = self.state.amount_propane - propane_remaining
        self.state.amount_propane = propane_remaining

        self.state.wood_income = self.coeffs.wood_price * \
            self.cooker.stock('wood') * fuel.Wood.coefficient(self.coeffs)

        if not self.state.water_pump:
            if not self.is_water_subsistence_met():
                self.message("insufficient water")
                self.dehydrate()

    def starve(self):
        # multiply by 180 in order to reverse the transformation to daily cals done in UI
        for (allocation,p) in zip(self.state.calorie_allocation,self.state.people):
            #p.starve(allocation * 180)
            p.update_health(allocation * 180, self.state.clinic, self.state.electricity)

    def dehydrate(self):
        for p in self.state.people:
            p.dehydrate(self.state.family_water_needs,
                        self.state.amount_water,
                        self.state.population)

    def num_infants(self):
        return len([p for p in self.state.people if p.is_infant()])

    def total_productivity(self):
        return sum([p.productivity() for p in self.state.people])

    def num_non_infants(self):
        return self.state.population - self.num_infants()

    def calc_avg_productivity(self):
        if self.num_non_infants() == 0:
            return 0.0
        if self.state.total_effort == 0:
            return 0.0
        s = 0.0
        for p in self.state.people:
            if p.is_infant():
                continue
            weighted = p.effort * p.productivity()
            s += weighted
        return (s / self.state.total_effort) / 100.0

    def update_avg_productivity(self):
        self.state.avg_productivity = self.calc_avg_productivity()

    def determine_income(self):
        self.state.income = 0
        self.state.tons_to_market = 0
        if self.state.food_to_sell > 0:
            (self.state.food_income,tons_food) = self.sell_food()
            self.state.income += self.state.food_income
        else:
            self.state.food_income = 0.0

        self.state.income += self.state.wood_income
        (cotton_income,tons_cotton) = self.sell_cotton()
        self.state.cotton_income = cotton_income
        self.state.income += cotton_income
        self.state.income += self.state.small_business_income
        self.state.tons_to_market = tons_cotton
        if (self.cost_of_wagon()) > 0 and (self.cost_of_wagon() > self.state.income + self.state.cash):
            # selling cotton would put them into debt because of
            # transport costs
            self.state.income -= cotton_income
            self.state.tons_to_market = 0
            self.state.cotton_income = 0
            self.message("transport too expensive")
        else:
            self.state.tons_to_market = tons_cotton
            self.state.expenditure = self.hire_wagon()
        self.state.income -= self.state.expenditure


    def transport_cost_per_ton(self):
        if self.state.road:
            return self.coeffs.transport_cost_road
        else:
            return self.coeffs.transport_cost_no_road

    def cost_of_wagon(self):
        return self.state.tons_to_market * self.transport_cost_per_ton() * 100.0

    def hire_wagon(self):
        cost_to_market = self.cost_of_wagon()
        self.state.cost_to_market = int(round(cost_to_market))
        return self.state.expenditure + cost_to_market

    def sell_food(self):
        totalToSell  = self.state.food_to_sell * (self.coeffs.maize_export_units / 100.0)
        income       = (totalToSell * self.coeffs.maize_price) / 1000.0
        if self.state.meals:
            # school meals raise prices by 20%
            income *= 1.20
        tons_to_market = totalToSell / 1000.0
        return (income,tons_to_market)

    def sell_cotton(self):
        total_to_sell = self.state.amount_cotton * (self.coeffs.cotton_export_units / 100.0)
        price = ((total_to_sell * self.coeffs.cotton_price) / 1000.0)
        tons_to_market = total_to_sell / 1000.0
        return (price,tons_to_market)
Exemple #27
0
            log_parser.getLog(srcfile)
            parsed_logfilename = FilePath.ROOTPATH + FilePath.LOGFILES + params[3]

        log_parser.saveParsedLog(parsed_logfilename,"w+")
    elif mode == "-learn":
        
        log_parser = LogParser()
        log_parser.loadParsedLog(FilePath.ROOTPATH + FilePath.PARSED_LOG)
        learning_engine = RoleInferenceEngine(log_parser)
        learning_engine.learnFromLog()
        learning_engine.checkEvaluations()
        learning_engine.saveParameters()

    elif mode == "-infer":
        role = params[2]
        role_inference_engine = RoleInferenceEngine()
        role_inference_engine.loadLearnedParameters()
        role_inference_engine.roleInferenceTest(role)
        #log_parser = LogParser()
        #log_parser.loadParsedLog(FilePath.ROOTPATH + FilePath.PARSED_LOG)
        #learning_engine =LogLearningEngine(log_parser)
        #learning_engine.learnFromLog()
        #learning_engine.roleInferenceTest(role)
    elif mode == "-game":
        village = Village(13)
        village.start()
    else:
        print "Invalid options"


Exemple #28
0
def main():
    parser = argparse.ArgumentParser(description="P0 Adventure")
    parser.add_argument(
        "--savefile",
        dest="savefile",
        default="game.json",
        help="The save file. default: 'game.json'",
    )
    parser.add_argument(
        "--new-game",
        dest="new_game",
        default=False,
        action="store_true",
        help="Create a new save file.",
    )
    parser.add_argument(
        "-b",
        dest="bonus_tasks",
        default=False,
        action="store_true",
        help="enable bonus tasks",
    )
    parser.add_argument(
        "--print-bonus",
        dest="print_bonus",
        default=False,
        action="store_true",
        help="print bonus task list and exit",
    )
    args = parser.parse_args()

    if args.print_bonus:
        print_bonus_tasks()
        return

    # your code starts here
    save = args.savefile
    if args.new_game:
        user = Player()
        user.createNewCharacter()
        gamedata = GameData(player=user, savefile=save, bonus_tasks=args.bonus_tasks)
        if args.bonus_tasks:
            totengraeber = Gravedigger()
            gamedata.gravedigger = totengraeber
            truhe = Chest()
            gamedata.chest = truhe

    else:
        gamedata = load_gamedata(save)
        user = gamedata.player
        if args.bonus_tasks:
            totengraeber = gamedata.gravedigger
            truhe = gamedata.chest

    schmied = Shopkeeper(name="blacksmith", inventory=blacksmith_items)
    druide = Shopkeeper(name="druid", inventory=druid_items)
    prog0 = Village(
        player=user, bonus_tasks=args.bonus_tasks, blacksmith=schmied, druid=druide
    )

    if args.bonus_tasks:
        prog0.gravedigger = totengraeber
        prog0.chest = truhe

    while True:
        user_choice = village(prog0)

        if user_choice == 5:
            dung0 = Dungeon(player=user, bonus_tasks=args.bonus_tasks)
            if args.bonus_tasks:
                dung0.gravedigger = totengraeber
            dungeon(dung0)
        elif user_choice == 6:
            save_gamedata(gamedata, save),
            print("Game saved to {}".format(save))
        elif user_choice == 0:
            quit(gamedata, save)
            break
        else:
            raise KeyError(
                "main.py Something went wrong with the user choosing what to do!"
            )

    sys.exit(0)
Exemple #29
0
class GameData():
    def place_resources(self):
        #And, yes, that's a really bad code.
        #TODO: Find some time to change it totally
        for i in range(0, 100):
            map_width = game_map.MAP_WIDTH * game_map.SQUARE_WIDTH
            map_height = game_map.MAP_HEIGHT * game_map.SQUARE_HEIGHT
            tile = self.game_map[random.randint(0, map_width)][random.randint(0, map_height)]
            if tile.ground != 'water':
                tile.resource = 'tree'
            tile = self.game_map[random.randint(0, map_width)][random.randint(0, map_height)]
            if tile.ground != 'water':
                tile.resource = 'stone'
            pos_w = random.randint(0, map_width)
            pos_h = random.randint(0, map_height)
            m_dist = abs(pos_w - self.center.x) + abs(pos_h - self.center.y)
            tile = self.game_map[pos_w][pos_h]
            if tile.ground != 'water' and m_dist > 20:
                tile.resource = 'iron'

    def place_center(self):
        self.center = Point(5, 5)
        while self.game_map[self.center.x][self.center.y].ground != 'grass':
            self.center.x += 1
            self.center.y += 1
        self.game_map[self.center.x][self.center.y].building = 'center'

    def place_monsters(self):
        self.monsters = []
        for i in range(0, 30):
            monster = Monster(self.game_map)
            monster.x = random.randint(0, game_map.MAP_WIDTH * game_map.SQUARE_WIDTH)
            monster.y = random.randint(0, game_map.MAP_HEIGHT * game_map.SQUARE_HEIGHT)
            monster.level = int(math.sqrt((self.center.x - monster.x) ** 2 + (self.center.y - monster.y) ** 2) / 50) + 1
            self.monsters.append(monster)
            self.game_map[monster.x][monster.y].units.append(monster)

    def __init__(self):
        self.drag = False
        self.done = False
        self.game_map = GameMap()
        generate_rivers(self.game_map)
        map_width = game_map.MAP_WIDTH * game_map.SQUARE_WIDTH
        map_height = game_map.MAP_HEIGHT * game_map.SQUARE_HEIGHT
        generate_swamp(self.game_map, Point(random.randint(0, map_width), random.randint(0, map_height)), random.randint(0, 30))
        self.place_center()
        self.place_resources()
        self.old_dx = 0
        self.old_dy = 0
        self.dx = -(300 - 32 * self.center.x)
        self.dy = -(300 - 32 * self.center.y)
        self.scroll_spd_x, self.scroll_spd_y = 0, 0
        self.exp_pos = None
        self.village = Village()
        self.expeditions = []
        self.turn = 0
        self.place_monsters()
        self.specialists = [Specialist(specialist.CHIEFTAIN)]
        self.last_time = time.time() * 1000
        self.accum = 0

    def send_expedition(self):
        self.uis.show_chose_specialists_dialog()

    def destroy_expedition(self, monster_tile, exp):
        exp.status = expedition.DEAD
        for spec in exp.warriors + exp.workers:
            self.specialists.remove(spec)
        self.village.population -= exp.people
        monster_tile.units.remove(exp)

    def move_monsters(self):
        for monster in self.monsters:
            self.game_map[monster.x][monster.y].units.remove(monster)
            monster.move()

            monster_tile = self.game_map[monster.x][monster.y]
            for unit in monster_tile.units:
                if isinstance(unit, expedition.Expedition):
                    if self.process_battle(monster, unit) == monster:
                        self.destroy_expedition(monster_tile, unit)
                    else:
                        self.destroy_monster(monster, monster_tile)
                        for specialist in unit.warriors:
                            specialist.add_exp(monster.level * 100)
                        break
            if monster_tile.building:
                self.village.remove_building(monster_tile.building)
                monster_tile.building = None
            if monster.alive:
                monster_tile.units.append(monster)

    def move_expeditions(self):
        for expedition_item in self.expeditions:
            self.game_map[expedition_item.x][expedition_item.y].units.remove(expedition_item)
            expedition_item.make_move()
            tile = self.game_map[expedition_item.x][expedition_item.y]
            for unit in tile.units:
                if type(unit) == Monster:
                    if self.process_battle(unit, expedition_item) == unit:
                        self.destroy_expedition(tile, unit)
                        break
                    else:
                        self.destroy_monster(unit, tile)
                        tile.units.remove(unit)
                        for specialist in expedition_item.warriors:
                            specialist.add_exp(unit.level * 100)
            if expedition_item.status == expedition.FINISHED:
                self.village.change_resource_count(expedition_item.resource, expedition_item.get_resources_count())
            else:
                tile.units.append(expedition_item)
        self.expeditions = filter(lambda x: x.status != expedition.FINISHED and x.status != expedition.DEAD,
                                  self.expeditions)

    def next_turn(self):
        self.turn += 1
        self.village.update()
        self.move_monsters()
        self.move_expeditions()

    def build(self, mouse_x, mouse_y):
        if not self.uis.building:
            return

        x = (self.dx + mouse_x) / 32
        y = (self.dy + mouse_y) / 32

        may_build = False
        if self.game_map[x][y].building:
            if self.uis.building == 'destruct' and self.uis.building != 'center':
                building = self.game_map[x][y].building
                finished = self.game_map[x][y].building_finished
                if finished:
                    self.game_map[x][y].building_finished = False
                    self.village.remove_building(building)
                    self.village.to_build.remove(building)
                self.game_map[x][y].building = None
            return
        if self.game_map[x][y].ground == 'water':
            return

        if self.game_map[x - 1][y].building:
            may_build = True
        if self.game_map[x - 1][y - 1].building:
            may_build = True
        if self.game_map[x - 1][y - 1].building:
            may_build = True
        if self.game_map[x][y - 1].building:
            may_build = True
        if self.game_map[x + 1][y - 1].building:
            may_build = True
        if self.game_map[x + 1][y].building:
            may_build = True
        if self.game_map[x + 1][y + 1].building:
            may_build = True
        if self.game_map[x][y + 1].building:
            may_build = True
        if may_build:
            self.set_building(x, y)

    def set_building(self, x, y):
        bm = BuildingManager()
        bc = bm.conds[self.uis.building]
        for resource in bc.resources:
            amount = self.village.get_resource_count(resource)
            if amount < bc.resources[resource]:
                return

        tile = self.game_map[x][y]
        for cond in bc.tile_params:
            if cond != tile.resource:
                return

        if not self.check_nearby_tiles(x, y, bc.near):
            return

        for resource in bc.resources:
            self.village.change_resource_count(resource, -bc.resources[resource])

        tile.building = self.uis.building
        tile.building_finished = False
        self.village.add_building(self.uis.building, tile)

    def check_nearby_tiles(self, x, y, cond):
        """Conditions for nearby tiles. Specially for port building"""
        points = (self.game_map[x][y - 1],
                  self.game_map[x + 1][y - 1],
                  self.game_map[x + 1][y],
                  self.game_map[x + 1][y + 1],
                  self.game_map[x][y + 1],
                  self.game_map[x - 1][y + 1],
                  self.game_map[x - 1][y],
                  self.game_map[x - 1][y - 1])
        for param in cond:
            result = False
            for point in points:
                result = getattr(point, param) == cond[param] or result
            if not result:
                return False
        return True

    def process_battle(self, monster, current_expedition):
        monster_power = monster.level * 100
        exp_power = 0
        for specialist in current_expedition.warriors:
            exp_power += specialist.level
        exp_power *= current_expedition.people
        if monster_power > exp_power:
            return monster
        return current_expedition

    def process(self):
        curr_time = time.time() * 1000
        delta = curr_time - self.last_time
        self.last_time = curr_time
        self.accum += delta

        if self.accum >= 100:
            self.accum -= 100
            self.dx += self.scroll_spd_x
            self.dy += self.scroll_spd_y

    def destroy_monster(self, monster, tile):
        monster.alive = False
        self.monsters.remove(monster)
        if not tile.resource:
            tile.resource = 'remaining'
    def __init(self, callback, conditions):
        self.conditions = conditions
        
        
if __name__ == '__main__':
    from village import Village
    from account import Account
    from resources import Resources
    from event import Event
    
    class K():
        @condition_changes(ConditionEnoughSpaceForResources)
        def handler_enought_space(self):
            print("enough!")
        
    vill = Village(Account((0,0), None), None, None, None)
    vill.suppress_refresh = True
    vill.resources = Resources((90,0,0,0))
    vill.production = Resources((1,0,0,0))
    vill.storage_capacity = Resources((100,0,0,0))
    vill.next_refresh_time = datetime(2220, 1, 1)
    
    inst = K()
    c = inst.handler_enought_space().enqueue(vill, Resources((20,0,0,0)))
    print("first check")
    vill.fire_event(Event(vill, 'resources_spent', datetime.now()))
    print("is true:", c.is_true())
    print("second check")
    vill.resources = Resources((0,0,0,0))
    vill.fire_event(Event(vill, 'resources_spent', datetime.now()))
    print("is true:", c.is_true())
Exemple #31
0
def init_game(input):
    village = Village(input["village"])
    friendships = Friendships(input["wordlist"])
    return village, friendships
Exemple #32
0
class Game:
    def __init__(self):
        self.menu = """
        Меню:
            1) Показать общую статистику о деревне
            2) Следующий день
            3) Изменить погоду
            4) Закончить игру
        """

        self.day = 1

        self.village = Village()
        self.player = Player()
        self.nature = Nature()
        self.world = World()
        self.world.add_nature(self.nature)
        self.world.add_player(self.player)
        self.village.add_player(self.player)

        for i in range(5):
            house = House()
            self.village.add_house(house)

        index = 1
        start_specialization = specialization
        list_spec = []
        for house in self.village.houses:
            for i in range(2):
                human = Human()
                spec = random.choice(start_specialization)
                list_spec.append(spec)
                if list_spec.count(spec) >= 4:
                    start_specialization.remove(spec)

                human.specialization = spec
                index += 1
                house.add_people(human)

        self.world.add_worker(self.village.get_people())

    def get_satiety_peaple(self):
        list_sat = []
        list_health = []
        list_name = []
        for hum in self.village.get_people():
            list_sat.append(hum.satiety)
            list_health.append(hum.health)
            list_name.append(hum.name)
        # print(list_sat)
        # print(list_health)
        # print(list_name)

    def check_new_peaple(self):
        part_food = self.village.get_surplus_food2()
        # print("part_food", part_food)
        if part_food >= 6:
            human = Human()
            self.village.add_human(human)
            faith = 10
            self.player.add_faith(faith)
            print(
                colored(
                    "Житель {} прибыл в деневню. Вера увеличилась на {}".
                    format(human.name, faith), "cyan"))

    def print_stat(self):
        dict_stat = self.village.short_paeple_statistic()
        short_stat_text = """Среднее здоровье людей: {}\nСредняя сытость людей: {}\nСреднее счастье людей: {}\nКоличество больных людей: {}\nВера: {}\nКоличество охотников: {}\nКоличество рыбаков {} \nКоличество собирателей {}""".format(
            dict_stat['health_peaple'],
            dict_stat['satiety_peaple'],
            dict_stat['fun_peaple'],
            dict_stat['illnesses_peaple'],
            dict_stat['faith'],
            dict_stat['hunters'],
            dict_stat['fisherman'],
            dict_stat['collectors'],
        )
        print(short_stat_text)

    def run(self):
        while True:
            print("\nДень: {}".format(self.day))
            print(self.village.news())
            print("Погода сейчас: {}".format(self.nature.weather_now_ru))
            self.get_satiety_peaple()
            print("Вера: {}".format(self.player.faith))
            print(self.menu)
            r = input("Твоя команда?: ")
            if r == '1':
                self.print_stat()
                # while True:
                #     r_stat = input("1) Назад\nТвоя команда?: ")
                #     if r_stat == '1':
                #         break
            elif r == '2':
                self.check_new_peaple()
                self.world.add_worker(self.village.get_people())
                self.nature.next_day()
                food = self.world.next_day()
                self.village.food += food
                self.village.next_day()

                col_peaple = self.village.check_peaple()
                if col_peaple == 0:
                    print(colored("Все жители умерли. Конец игры!", "red"))
                    break

                self.day += 1
            elif r == '3':
                print(self.nature.get_weather_info())
                while True:
                    print("&!" * 10)
                    rate = input(
                        "На пунктов изменить погоду?\nОт -50 до 50. 1 пункт равен 3 манны.\nОтвет: "
                    )
                    if -50 <= int(rate) <= 50:
                        self.nature.add_weather_rate(int(rate))
                        self.player.faith -= abs(int(rate) * 3)
                        print("Уровень веры: ", self.player.faith)
                        print(self.nature.get_weather_info())
                        break
            # elif r == '5':
            #     print(self.nature.get_weather_info())
            #     self.nature.add_weather_rate(random.randint(-10, -50))
            elif r == '4':
                break
            else:
                print(colored("Я не знаю такой команды", "red"))