Skip to content

Commit 5098bb6

Browse files
committed
Article 3 files.
1 parent ca28d0c commit 5098bb6

File tree

4 files changed

+93
-62
lines changed

4 files changed

+93
-62
lines changed

MattEland.FSharpGeneticAgorithm.ConsoleTestApp/Display.fs

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ let printCell char isLastCell =
1010
else
1111
printf "%c" char
1212

13-
let displayWorld (world: World) =
13+
let displayWorld (world: World) turnsRemaining =
14+
printfn ""
15+
printfn "%i turn(s) remaining" turnsRemaining
1416
printfn ""
1517

1618
for y in 1..world.MaxX do
@@ -36,7 +38,7 @@ let displayWorld (world: World) =
3638
Console.ForegroundColor <- ConsoleColor.White
3739

3840
let getUserInput(state: GameState): ConsoleKeyInfo =
39-
displayWorld state.World
41+
displayWorld state.World state.TurnsLeft
4042
printfn ""
4143

4244
match state.SimState with

MattEland.FSharpGeneticAgorithm.ConsoleTestApp/Program.fs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
open System
2-
open MattEland.FSharpGeneticAlgorithm.Logic.Actors
32
open MattEland.FSharpGeneticAlgorithm.Logic.Simulator
43
open MattEland.FSharpGeneticAlgorithm.Logic.WorldGeneration
54
open MattEland.FSharpGeneticAlgorithm.Logic.Commands
@@ -34,7 +33,7 @@ let main argv =
3433

3534
let world = makeTestWorld false
3635

37-
let mutable state = { World = world; SimState = Simulating}
36+
let mutable state = { World = world; SimState = Simulating; TurnsLeft=30}
3837
let mutable simulating: bool = true
3938

4039
while simulating do

MattEland.FSharpGeneticAlgorithm.Logic/Simulator.fs

+49-36
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ open MattEland.FSharpGeneticAlgorithm.Logic.WorldGeneration
88

99
type SimulationState = Simulating | Won | Lost
1010

11-
type GameState = { World : World; SimState: SimulationState }
11+
type GameState = { World : World; SimState: SimulationState; TurnsLeft: int}
1212

1313
let canEnterActorCell actor target =
1414
match target with
@@ -19,6 +19,7 @@ let canEnterActorCell actor target =
1919

2020
let moveActor state actor pos =
2121
let world = state.World
22+
2223
let performMove =
2324
let actor = { actor with Pos = pos }
2425
match actor.ActorKind with
@@ -28,46 +29,48 @@ let moveActor state actor pos =
2829
| Rabbit -> { state with World={world with Rabbit = actor }}
2930
| Doggo -> { state with World={world with Doggo = actor }}
3031

32+
let handleDogMove state otherActor =
33+
if otherActor.ActorKind = Rabbit then
34+
{state with World = {world with
35+
Rabbit = {world.Rabbit with IsActive = false}
36+
Doggo = {world.Doggo with Pos = pos}
37+
}}
38+
else
39+
{state with SimState = Lost; World = {world with
40+
Squirrel = {world.Squirrel with IsActive = false}
41+
Doggo = {world.Doggo with Pos = pos}
42+
}
43+
}
44+
45+
let handleSquirrelMove otherActor hasAcorn =
46+
if not hasAcorn && otherActor.ActorKind = Acorn && otherActor.IsActive then
47+
// Moving to the acorn for the first time should give the squirrel the acorn
48+
{state with World =
49+
{
50+
world with
51+
Squirrel = {ActorKind = Squirrel true; Pos = pos; IsActive = true}
52+
Acorn = {world.Acorn with IsActive = false}
53+
}
54+
}
55+
else if hasAcorn && otherActor.ActorKind = Tree then
56+
// Moving to the tree with the acorn - this should win the game
57+
{
58+
state with SimState = Won; World = {
59+
world with Squirrel = {ActorKind = Squirrel true; Pos = pos; IsActive = true}
60+
}
61+
}
62+
else
63+
performMove
64+
3165
let target = tryGetActor(pos.X, pos.Y) world
3266

3367
match target with
3468
| None -> performMove
3569
| Some otherActor ->
3670
if otherActor <> actor && canEnterActorCell actor.ActorKind otherActor.ActorKind then
37-
3871
match actor.ActorKind with
39-
| Doggo ->
40-
if otherActor.ActorKind = Rabbit then
41-
{state with World = {world with
42-
Rabbit = {world.Rabbit with IsActive = false}
43-
Doggo = {world.Doggo with Pos = pos}
44-
}}
45-
else
46-
{state with SimState = Lost; World = {world with
47-
Squirrel = {world.Squirrel with IsActive = false}
48-
Doggo = {world.Doggo with Pos = pos}
49-
}
50-
}
51-
52-
| Squirrel hasAcorn ->
53-
if not hasAcorn && otherActor.ActorKind = Acorn && not otherActor.IsActive then
54-
// Moving to the acorn for the first time should give the squirrel the acorn
55-
{state with World =
56-
{
57-
world with
58-
Squirrel = {ActorKind = Squirrel true; Pos = pos; IsActive = true}
59-
Acorn = {world.Acorn with IsActive = false}
60-
}
61-
}
62-
else if hasAcorn && otherActor.ActorKind = Tree then
63-
// Moving to the tree with the acorn - this should win the game
64-
{
65-
state with SimState = Won; World = {
66-
world with Squirrel = {ActorKind = Squirrel true; Pos = pos; IsActive = true}
67-
}
68-
}
69-
else
70-
performMove
72+
| Doggo -> handleDogMove state otherActor
73+
| Squirrel hasAcorn -> handleSquirrelMove otherActor hasAcorn
7174
| _ -> performMove
7275
else
7376
state
@@ -104,9 +107,19 @@ let simulateDoggo (state: GameState) =
104107
else
105108
state
106109

110+
let decreaseTimer (state: GameState) =
111+
if state.SimState = Simulating then
112+
if state.TurnsLeft > 0 then
113+
{state with TurnsLeft = state.TurnsLeft - 1}
114+
else
115+
{state with TurnsLeft = 0; SimState = Lost}
116+
else
117+
state
118+
107119
let simulateActors (state: GameState) getRandomNumber =
108120
moveRandomly state state.World.Rabbit getRandomNumber
109-
|> simulateDoggo
121+
|> simulateDoggo
122+
|> decreaseTimer
110123

111124
let handlePlayerCommand state command =
112125
let player = state.World.Squirrel
@@ -131,7 +144,7 @@ let handlePlayerCommand state command =
131144
let playTurn state getRandomNumber command =
132145
let world = state.World
133146
match command with
134-
| Restart -> { World = makeWorld world.MaxX world.MaxY getRandomNumber; SimState = Simulating }
147+
| Restart -> { World = makeWorld world.MaxX world.MaxY getRandomNumber; SimState = Simulating; TurnsLeft = 30 }
135148
| _ ->
136149
match state.SimState with
137150
| Simulating ->
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
module MattEland.FSharpGeneticAlgorithm.Tests
22

3-
open System
43
open Xunit
54
open FsUnit
65
open MattEland.FSharpGeneticAlgorithm.Logic.WorldPos
@@ -21,16 +20,17 @@ let ``Point Adjaency Tests`` (x1, y1, x2, y2, expectedAdjacent) =
2120
// Act & Assert
2221
isAdjacentTo pos1 pos2 |> should equal expectedAdjacent
2322

23+
let getRandomNumber (max: int): int = 42
24+
let buildTestState = {World=(makeTestWorld false); SimState=Simulating; TurnsLeft = 30}
25+
2426
[<Fact>]
2527
let ``Rabbit should move randomly`` () =
2628
// Arrange
27-
let randomizer = new Random(42)
28-
let world: World = makeTestWorld false
29-
let state: GameState = {World=world; SimState=Simulating}
29+
let state = buildTestState
3030
let originalPos = state.World.Rabbit.Pos
3131

3232
// Act
33-
let newWorld = simulateActors state randomizer.Next
33+
let newWorld = simulateActors state getRandomNumber
3434

3535
// Assert
3636
newWorld.World.Rabbit.Pos |> should not' (equal originalPos)
@@ -39,12 +39,11 @@ let ``Rabbit should move randomly`` () =
3939
let ``Squirrel Getting Acorn Should Change how it Displays`` () =
4040
// Arrange
4141
let customSquirrel = {Pos=newPos 6 7; ActorKind = Squirrel false; IsActive = true}
42-
let world: World = {(makeTestWorld false) with Squirrel = customSquirrel}
43-
let state: GameState = {World=world; SimState=Simulating}
44-
let command: GameCommand = MoveLeft
42+
let testState = buildTestState
43+
let state: GameState = {testState with World = {testState.World with Squirrel = customSquirrel}}
4544

4645
// Act
47-
let newState = handlePlayerCommand state command
46+
let newState = handlePlayerCommand state MoveLeft
4847

4948
// Assert
5049
newState.World.Squirrel.ActorKind |> should equal (Squirrel true)
@@ -53,31 +52,49 @@ let ``Squirrel Getting Acorn Should Change how it Displays`` () =
5352
let ``Squirrel Getting Acorn to Tree Should Win Game`` () =
5453
// Arrange
5554
let customSquirrel = {Pos=newPos 9 10; ActorKind = Squirrel true; IsActive = true}
56-
let world: World = {(makeTestWorld false) with Squirrel = customSquirrel}
57-
let state: GameState = {World=world; SimState=Simulating}
58-
let command: GameCommand = MoveLeft
55+
let testState = buildTestState
56+
let state: GameState = {testState with World = {testState.World with Squirrel = customSquirrel}}
5957

6058
// Act
61-
let newState = handlePlayerCommand state command
59+
let newState = handlePlayerCommand state MoveLeft
6260

6361
// Assert
64-
newState.World.Squirrel.Pos |> should equal world.Tree.Pos
62+
newState.World.Squirrel.Pos |> should equal state.World.Tree.Pos
6563
newState.SimState |> should equal Won
66-
6764

6865
[<Fact>]
69-
let ``Squirrel Moving Next to Dog Should End With Squirrel Eaten`` () =
66+
let ``Dog Should Eat Squirrel If Adjacent`` () =
7067
// Arrange
71-
let randomizer = new Random(42)
7268
let customSquirrel = {Pos=newPos 3 6; ActorKind = Squirrel false; IsActive = true}
73-
let world: World = {(makeTestWorld false) with Squirrel = customSquirrel}
74-
let state: GameState = {World=world; SimState=Simulating}
69+
let testState = buildTestState
70+
let state: GameState = {testState with World = {testState.World with Squirrel = customSquirrel}}
7571

7672
// Act
77-
let newState = simulateActors state randomizer.Next
73+
let newState = simulateActors state getRandomNumber
7874

7975
// Assert
80-
newState.World.Doggo.Pos |> should equal world.Squirrel.Pos
76+
newState.World.Doggo.Pos |> should equal newState.World.Squirrel.Pos
8177
newState.World.Squirrel.IsActive |> should equal false
8278
newState.SimState |> should equal Lost
83-
79+
80+
[<Fact>]
81+
let ``Simulating actors should decrease the turns left counter`` () =
82+
// Arrange
83+
let initialState = buildTestState
84+
85+
// Act
86+
let newState = simulateActors initialState getRandomNumber
87+
88+
// Assert
89+
newState.TurnsLeft |> should equal (initialState.TurnsLeft - 1)
90+
91+
[<Fact>]
92+
let ``Running out of turns should lose the simulation`` () =
93+
// Arrange
94+
let state: GameState = {buildTestState with TurnsLeft = 0}
95+
96+
// Act
97+
let newState = simulateActors state getRandomNumber
98+
99+
// Assert
100+
newState.SimState |> should equal Lost

0 commit comments

Comments
 (0)