/
ItemRandomizer.elm
79 lines (70 loc) · 3.29 KB
/
ItemRandomizer.elm
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
module ItemRandomizer where
import GameLogic (collision)
import InputModel (GamePiece, Item)
import TextField
import KittenConstants
import String (fromList)
-- a number to use as a seed for a random number generator.
-- using a larger time interval than the game is likely to take
-- (or a browser instance is likely to survive) provides the
-- illusion that items can't change location, color, and symbol
-- right in front of the player.
interval : Bool -> Time
interval small =
if small then 1000 * 2
else 1000 * 60 * 60 * 24 * 7 * 365 --update every year (non-leap ;) )
-- process the signal so it can be used as an RNG seed.
initialSeed : Bool -> Signal Int
initialSeed small =
lift floor (every (interval small))
-- remove the element with the index given from the list;
-- return the element in the index and the list with the
-- element excised.
removeIndex : Int -> [a] -> (a, [a])
removeIndex index list =
let firstChunk = reverse (take index list)
lastChunk = drop index list
item = head firstChunk
remaining = reverse (tail firstChunk)
in
(item, (remaining ++ lastChunk))
-- given some random numbers and bounds on possible locations,
-- generate locations, colors, and descriptions for items.
generateCommonAttributes : (Int, Int) -> [Int] -> GamePiece {}
generateCommonAttributes (w, h) randomInts =
let (randX::randY::randR::randG::randB::randSymbolIndex::others) = randomInts
(columnLimit, rowLimit) =
TextField.toCartesianLimits <|
TextField.makeLimits (w, h)
-- negatives are OK for location, hence the unusual use of `rem`
location = (randX `rem` columnLimit, randY `rem` rowLimit)
col = rgb (randR % 256) (randG % 256) (randB % 256)
(symbol, _) = removeIndex ((randSymbolIndex % (length KittenConstants.characters)) + 1) KittenConstants.characters
in
{ char = fromList [symbol], cd = col, xd = fst location, yd = snd location }
makeKitten : (Int, Int) -> [Int] -> Item (GamePiece {})
makeKitten (w, h) randomInts =
let baseRecord = generateCommonAttributes (w, h) randomInts
kittened = { baseRecord | isKitten = True}
in
{ kittened | description = KittenConstants.kittenDescription }
avoidCollisions : GamePiece a -> [GamePiece b] -> GamePiece a
avoidCollisions newItem existingItems =
case (collision newItem existingItems) of
Just x -> avoidCollisions { newItem | xd <- (//) (newItem.xd * -1) 2} existingItems
Nothing -> newItem
generateItem : (Int, Int) -> [String] -> [Int] -> ([String], Item (GamePiece {}))
generateItem (w, h) descs randomInts =
let baseRecord = generateCommonAttributes (w, h) randomInts
randDescIndex = head (drop 6 randomInts)
(description, unusedDescs) = removeIndex ((randDescIndex % (length descs)) + 1) descs
notKitten = { baseRecord | isKitten = False }
in
(unusedDescs, { notKitten | description = description })
generateItems : (Int, Int) -> [String] -> [Int] -> Int -> [Item (GamePiece {})]
generateItems (w, h) descs randomInts howMany =
if howMany <= 0 || (length descs == 0) then [makeKitten (w, h) randomInts]
else
let (unusedDescs, item) = generateItem (w, h) descs randomInts
otherItems = (generateItems (w, h) unusedDescs (drop 7 randomInts) (howMany - 1)) in
(avoidCollisions item otherItems) :: otherItems