/// <summary>Updates the state.</summary> public State Update(Serialization.Game game) { var state = new State() { hero1 = Hero.Create(game.heroes[0]), hero2 = Hero.Create(game.heroes[1]), hero3 = Hero.Create(game.heroes[2]), hero4 = Hero.Create(game.heroes[3]), ownership = ownership.UpdateFromTiles(game.board.tiles), }; state.hash = GetHash(game.turn, state.hero1, state.hero2, state.hero3, state.hero4); return(state); }
/// <summary>The hero moves.</summary> /// <remarks> /// If the hero: /// /// * Tries to step out of the map, or over a tree, nothing happens. /// /// * Steps into a gold mine, he stays in place, and: /// - If the mine already belongs to the hero, nothing happens. /// - If the mine is neutral, or belongs to another hero, a fight /// happens against the goblin guarding the mine. The hero loses /// 20 life points. If he survives, the mine is his. /// /// * Steps into another hero, he stays in place and nothing happens. /// Hero fights are resolved at the end of the turn. /// /// * Steps into a tavern, he stays in place and orders a beer. The hero /// pays 2 gold and receive 50HP. Note than HP can never exceed 100. /// /// * Times out, i.e. fails to send an order in the given delay (1 second), /// he stays in place until the game is finished. Note that he can /// still win if he as more gold than the other players at the end /// of the game. /// /// /// After the hero has moved, a few things happen: /// /// ::Fights /// Heroes are quite nervous and never miss an opportunity to slap each /// others with their big blades. After the hero has moved, if there is /// an enemy at a distance of one square in any direction, the hero /// attacks the enemy. For instance, in this situation, /// after Hero 1 (@1) has moved: /// /// @1@2 /// @3 /// /// @1 attacks @2. @1 does not attack @3 because it's 2 moves away. /// The attacking hero doesn't lose any life point, the defending one /// loses 20 life points. /// If the defender dies (see: Death of a hero), the attacking hero /// obtains control of all the loser's gold mines. /// /// ::Mining /// After the hero has moved, he gains one gold per controlled mine. /// /// ::Thirst /// /// After the hero has moved, he loses one HP (because all this action made him thirsty). /// Note that heroes don't die of thirst. Worse case, they fall to 1 HP. /// </remarks> public State Move(Map map, Hero hero, PlayerType player, Tile source, Tile target) { unchecked { #if DEBUG var test = GetHero(player); if (hero != test) { throw new Exception("Invalid hero."); } #endif var state = new State() { hero1 = hero1, hero2 = hero2, hero3 = hero3, hero4 = hero4, ownership = ownership, }; var health = hero.Health; int mines = hero.Mines; int gold = hero.Gold; // Try to get a mine. if (target.MineIndex > -1) { var ownerPlayer = state.ownership[target.MineIndex]; // Try to get the mine. if (ownerPlayer != player) { health = health.Slammed(); if (health.IsAlive) { mines++; state.ownership = state.ownership.Set(target.MineIndex, player); if (ownerPlayer != PlayerType.None) { var ownerHero = state.GetHero(ownerPlayer); ownerHero = ownerHero.LoseMine(ownerHero.Mines); state.SetHero(ownerPlayer, ownerHero); } } } target = source; } // Drink a beer. else if (target.TileType == TileType.Tavern) { target = source; if (gold >= Hero.CostsTavern) { gold -= Hero.CostsTavern; health = health.Drink(); } } // move or combat. else { var occupied = state.GetOccupied(target, player); if (occupied != PlayerType.None) { target = source; } } // died trying to get a mine. if (health.IsDead) { state.ownership = state.ownership.ChangeOwnership(player, PlayerType.None, map.Mines.Length); hero = Hero.Respawn(map.GetSpawn(player), gold); } // try to battle. else { foreach (var other_player in PlayerTypes.Other[player]) { var other_hero = state.GetHero(other_player); var other_tile = map[other_hero]; foreach (var neighbor_tile in other_tile.Neighbors) { if (neighbor_tile == target) { var other_health = other_hero.Health.Slammed(); if (other_health.IsDead) { var other_gold = other_hero.Gold; mines += other_hero.Mines; state.SetHero(other_player, Hero.Respawn(map.GetSpawn(other_player), other_gold)); if (map.Mines.Length > 28) { } state.ownership = state.ownership.ChangeOwnership(other_player, player, map.Mines.Length); } else { state.SetHero(other_player, other_hero.SetHealth(other_health)); } break; } } } gold += mines; health = health.Step(); hero = Hero.Create(health, target, mines, gold); } state.SetHero(player, hero); #if DEBUG if (state.hero1.Mines != state.Mines.Count(PlayerType.Hero1) || state.hero2.Mines != state.Mines.Count(PlayerType.Hero2) || state.hero3.Mines != state.Mines.Count(PlayerType.Hero3) || state.hero4.Mines != state.Mines.Count(PlayerType.Hero4)) { throw new Exception("Invalid state"); } #endif state.hash = GetHash(this.Turn + 1, state.hero1, state.hero2, state.hero3, state.hero4); return(state); } }
/// <summary>The hero moves.</summary> /// <remarks> /// If the hero: /// /// * Tries to step out of the map, or over a tree, nothing happens. /// /// * Steps into a gold mine, he stays in place, and: /// - If the mine already belongs to the hero, nothing happens. /// - If the mine is neutral, or belongs to another hero, a fight /// happens against the goblin guarding the mine. The hero loses /// 20 life points. If he survives, the mine is his. /// /// * Steps into another hero, he stays in place and nothing happens. /// Hero fights are resolved at the end of the turn. /// /// * Steps into a tavern, he stays in place and orders a beer. The hero /// pays 2 gold and receive 50HP. Note than HP can never exceed 100. /// /// * Times out, i.e. fails to send an order in the given delay (1 second), /// he stays in place until the game is finished. Note that he can /// still win if he as more gold than the other players at the end /// of the game. /// /// /// After the hero has moved, a few things happen: /// /// ::Fights /// Heroes are quite nervous and never miss an opportunity to slap each /// others with their big blades. After the hero has moved, if there is /// an enemy at a distance of one square in any direction, the hero /// attacks the nemy. For instance, in this situation, /// after Hero 1 (@1) has moved: /// /// @1@2 /// @3 /// /// @1 attacks @2. @1 does not attack @3 because it's 2 moves away. /// The attacking hero doesn't lose any life point, the defending one /// loses 20 life points. /// If the defender dies (see: Death of a hero), the attacking hero /// obtains control of all the loser's gold mines. /// /// ::Mining /// After the hero has moved, he gains one gold per controlled mine. /// /// ::Thirst /// /// After the hero has moved, he loses one HP (because all this action made him thirsty). /// Note that heroes don't die of thirst. Worse case, they fall to 1 HP. /// </remarks> public State Move(Map map, Hero hero, PlayerType player, Tile source, Tile target) { unchecked { var state = new State() { turn = (ushort)(turn + 1), hero1 = hero1, hero2 = hero2, hero3 = hero3, hero4 = hero4, mines0 = mines0, mines1 = mines1, }; int health = hero.Health; int mines = hero.Mines; int gold = hero.Gold; // Try to get a mine. if (target.MineIndex > -1) { var ownerPlayer = state.GetMine(target.MineIndex); // Try to get the mine. if (ownerPlayer != player) { health = Math.Max(Hero.HealthMin, health - Hero.HealthBattle); if (health > Hero.HealthMin) { mines++; state.SetMine(target.MineIndex, player); if (ownerPlayer != PlayerType.None) { var ownerHero = state.GetHero(ownerPlayer); ownerHero = ownerHero.LoseMine(ownerHero.Mines); state.SetHero(ownerPlayer, ownerHero); } } } target = source; } // Drink a beer. else if (target.TileType == TileType.Taverne) { target = source; if (gold >= Hero.CostsTavern) { gold -= Hero.CostsTavern; health = Math.Min(health + Hero.HealthTavern, Hero.HealthMax); } } // move or combat. else { var occupied = state.GetOccupied(target, player); if (occupied != PlayerType.None) { target = source; } } // died trying to get a mine. if (health == Hero.HealthMin) { hero = Hero.Respawn(map.GetSpawn(player), gold); } // try to battle. else { foreach (var other_player in PlayerTypes.Other[player]) { var other_hero = state.GetHero(other_player); var other_tile = map[other_hero]; foreach (var neighbor_tile in other_tile.Neighbors) { if (neighbor_tile == target) { var other_health = other_hero.Health; if (other_health <= Hero.HealthBattle) { var other_gold = other_hero.Gold; mines += other_hero.Mines; state.SetHero(other_player, Hero.Respawn(map.GetSpawn(other_player), other_gold)); state.SetMines(map, other_gold, other_player, player); } break; } } } gold += mines; health = Math.Max(Hero.HealthThirst, health - Hero.HealthThirst); hero = Hero.Create(health, target, mines, gold); } state.SetHero(player, hero); return(state); } }