๐Ÿ“ฆ sleepyfran / duets

๐Ÿ“„ World.fs ยท 64 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64module Duets.Data.World.World

open Duets.Entities

/// Generates the game world. Right now only creates a hard-coded city with
/// a bunch of places interconnected, in the future this should procedurally
/// generate the world and all the cities in it.
let private generate () =
    let london = Cities.London.Root.generate ()
    let losAngeles = Cities.LosAngeles.Root.generate ()
    let madrid = Cities.Madrid.Root.generate ()
    let newYork = Cities.NewYork.Root.generate ()
    let prague = Cities.Prague.Root.generate ()

    World.create [ london; losAngeles; madrid; newYork; prague ]

/// Returns the game world. The world is initialized when the module is loaded.
let get = generate ()

/// Defines the metadata about the country a certain city belongs to.
let private countryMetadata: Map<CityId, CountryId> =
    [ (London, England)
      (LosAngeles, UnitedStates)
      (Madrid, Spain)
      (NewYork, UnitedStates)
      (Prague, CzechRepublic) ]
    |> Map.ofList

/// Returns the country of the given city.
let countryOf city = countryMetadata |> Map.find city

/// Defines different metadata about the connections between cities: the
/// distance between them and which connections are available (road, sea or air)
let private connectionMetadata
    : Map<CityId * CityId, CityConnectionDistance * CityConnections> =
    [ ((London, LosAngeles), (8800<km>, [ Air ]))
      ((London, Madrid), (1260<km>, [ Road; Air ]))
      ((London, NewYork), (5570<km>, [ Air ]))
      ((London, Prague), (1035<km>, [ Road; Air ]))
      ((LosAngeles, Madrid), (9120<km>, [ Air ]))
      ((LosAngeles, NewYork), (3930<km>, [ Air; Road ]))
      ((LosAngeles, Prague), (9640<km>, [ Air ]))
      ((Madrid, NewYork), (5768<km>, [ Air ]))
      ((Madrid, Prague), (1780<km>, [ Road; Air ]))
      ((NewYork, Prague), (6570<km>, [ Air ])) ]
    |> Map.ofList

/// Returns the distance between the given cities.
let distanceBetween city1 city2 =
    let key = if city1 < city2 then (city1, city2) else (city2, city1)
    connectionMetadata |> Map.find key |> fst

/// Returns all cities that can be reached by road from the given city.
let citiesReachableByRoadFrom cityId =
    connectionMetadata
    |> Map.toList
    |> List.collect (fun ((city1, city2), (distance, connections)) ->
        if connections |> List.contains Road then
            if city1 = cityId then [ (city2, distance) ]
            elif city2 = cityId then [ (city1, distance) ]
            else []
        else
            [])