friendz: save level on level change and game quit
[nit.git] / contrib / friendz / src / level.nit
1 # Monsterz - Chains of Friends
2 #
3 # 2010-2014 (c) Jean Privat <jean@pryen.org>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the Do What The Fuck You Want To
7 # Public License, Version 2, as published by Sam Hocevar. See
8 # http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9
10 # Level managment
11 module level
12
13 import grid
14
15 # A level in the game
16 class Level
17 # The associated game
18 var game: Game
19
20 init(game: Game, i: Int, code: String)
21 do
22 self.game = game
23 var ls = code.split(";")
24 self.number = i
25 self.str = ls[0]
26 self.gold = ls[1].to_i
27 if ls.length >= 3 then
28 self.status = ls[2]
29 end
30 self.is_tutorial = i<=4
31 self.is_challenge = i>=25
32 if self.is_tutorial then
33 self.name = "T{i+1}"
34 self.fullname = "Tutorial level {i+1}"
35 else if not self.is_challenge then
36 self.name = (i-4).to_s
37 self.fullname = "Level {i-4}"
38 else
39 self.name = "C{i-24}"
40 self.fullname = "Challenge level {i-24}"
41 end
42 end
43
44 # number the level (0 for first)
45 var number: Int
46
47 # initial grid position
48 var str: String
49
50 # top score to get gold
51 var gold: Int
52
53 # Help message if any
54 var status: String = ""
55
56 # Is the level a tutorial level?
57 var is_tutorial: Bool
58
59 # Is the level a challenge level?
60 var is_challenge: Bool
61
62 # The short name of the level (eg. "T1")
63 var name: String
64
65 # The long name of the level (eg. "Tutorial level 1")
66 var fullname: String
67
68 # The player best wining score.
69 # 0 it not yet won
70 var score = 0
71
72 var l_disabled = 1
73 var l_open = 2
74 var l_won = 3
75 var l_gold = 4
76
77 fun get_state: Int
78 do
79 if self.score == 0 then
80 if self.number == 0 or game.levels[self.number-1].score > 0 then return l_open
81 if self.number == 25 and game.levels[19].score > 0 then return l_open else return l_disabled
82 else if self.score < self.gold or not game.levels[9].score > 0 then
83 return l_won
84 else return l_gold
85 end
86
87 # Returns true if g is a wining condition for the level.
88 fun check_won(g: Grid): Bool
89 do
90 var w = g.won and (not self.is_challenge or g.number >= self.gold)
91 if not w then return false
92 if g.number > self.score then
93 self.score = g.number
94 end
95 return true
96 end
97 end
98
99 # main game object
100 class Game
101 # Game version
102 var version = "1.99"
103
104 # Names of kind of monsters @constant
105 var colors: Array[nullable String] = [null, "Red", "Cyan", "Green", "Purple", "Yellow", "Orange", "Blue", "Pink", "White"]
106
107 # max grid width
108 var gw = 16
109
110 # max grid height
111 var gh = 16
112
113 # Number of monster kinds (+1 for empty) @constant
114 var monsters = 9
115
116 # The grid to play on
117 var grid = new Grid(gw, gh, monsters)
118
119 # LEVELS ******************************************************************
120
121 # Raw level description
122 var levels_code: Array[String] = [
123 ".3#|A2.A|3#.|;6;Connect two monsters",
124 ".#.|A.#|#.A|;5;Diagonals do not count",
125 "2.A|A#.|2.A|;8;Connect all monsters",
126 "3A.|3.A|2.A.|;10;Only 1 or 2 neighbors",
127 "2.A.|.B.B|2.A.|;12;Build two chains",
128
129 "A.A#|4.|#.#.|A3.|;11",
130 "A2.#A|5.|2.A2.|4.#|4.A|;17",
131 "A2.B2.|.B2.A.|6.|.AB2.B|6.|6.|;36",
132 "A5.|B5.|#.A3.|6.|2.A.B.|.A4.|;26",
133 "8.|BA2.B.A.|2.C.C.B.|6.#.|;29",
134
135 ".B3.B|6.|.#3.#|.C3.B|.#4.|6.|.C3.C|;30",
136 ".A.#4.|.C3.A.E|.A6.|6.C.|8.|2.6#|6.E#|5.C2#|;54",
137 ".A5.A|.A.#3.A|2.#A.#.#|.#.#4.|2.A3.#.|8.|4.A2.A|2.A2.A.#|;37",
138 "AB3.C|2.AC2.|6.|.B.CB.|6.|;30",
139 "AC5#CA|2.#3.#2.|4.#4.|7.#.|5.#.#.|9.|2.G6.|6.2#.|9.|H#F#G#F#H|;72",
140
141 "AG3.C|2.AC2.|6.|.G2.G.|2.C3.|6.|;32",
142 "7.#2.|3.#.#4.|.#8.|7.D2.|2.#.3#3.|2.#3.2#FC|9..|2.2#3.FCD|9..|;71",
143 "2.#A4.|6.B.|.C6.|.A.A.AC.|#7.|5.B2.|8.|#A5.C|;56",
144 "9.3.|8.#3.|2.B.#3.BA2.|2.AC4.DC2.|2.EA8.|8.#3.|.2#3.#5.|7.#4.|2#3.#B5.|5.CD5.|.2#9.|3.E8.|;119",
145 "9.7.|.2#B8#E2#.|.E8.#3.#.|.#3.4#.#.#.#.|.#.#.#4.#.#.#.|.C.#3.2#.#.#.#.|.#.#.4#3.#.#.|.D8.3#.#.|.#.#.4#5.A.|.A5.#2.#.3#.|.3#.#.2#.#2.2#.|.D3.#4.2#2.#.|.#.3#.#.4#.#.|.#5.#6.#.|.3#C6#B3#.|9.7.|;130",
146
147 "8.|.#C2.C#.|.#E2.E#.|8.|8.|.B#2.#A.|.#C2.C#.|8.|8.|.BF2.FA.|.2#2.2#.|8.|8.|.2#2.2#.|.A#2.B#.|8.|;92",
148 ".A9..|D9.F.|7.CA3.|3.E8.|9.2.H|9.2.#|7.G4.|4.BG2.F3.|2.B6.E2.|9.G2.|.H8.C.|8.D3.|;140",
149 "2.F9..|2.C9..|9..C2.|8.AG3.|9.4.|4.2#5.F.|7.E4.#|3.A9.|.G.CF4.C.#.|9.2.E.|;125",
150 "9.HCB|.DH9.|.GC9.|9.3.|4.G7.|3.#8.|9.3.|3.B4.D3.|.G9..|8.#3.|2.C2.2#5.|9.3.|;135",
151 "9.6.A|6.C9.|2.A.B4.E3.#I.|9.I.#4.|9.7.|2.E3.C9.|7.B8.|5.G6.G3.|6.C6.G2.|9..H3.B.|.CH.#5.#2.C2.|4.H3.#3.H3.|.B3.F5.F4.|.D.D4.D5.D.|9.7.|6.C9.|;244",
152
153 "E6.|7.|.F.E.F.|.F.#.E.|.F.E.E.|7.|6.F|;48",
154 "3.2#3.|2.A2.A2.|.C4.C.|8.|3.2#3.|2.A2.A2.|.C4.C.|8.|;56",
155 "3.#3.A4.|5.#6.|3.#5.#2.|.#4.#4.#|4.#7.|#6.#4.|8.#3.|.#9..|.#3.#4.#.|3.2#3.#3.|;74",
156 "2.A7.|2.D7.|2.A4.A2.|2.G4.G2.|2.A4.D2.|2.D7.|2.A7.|2.G7.|2.D7.|2.G7.|;95",
157 "E9.6.|9.H4.#.|9.E2.#3.|9.F2.#2.#|9.3.H2.#|HEF9.3.#|9.7.|6.#9.|6.#2.H3.HEF|.6#2.E6.|9.F6.|5#9.2.|4.#9.#.|.F#3.7#.#.|9.5.#.|9.7.|;225"
158 ]
159
160 # The loaded levels
161 var levels = new Array[Level]
162
163 # Load levels
164 # used duting `init`
165 fun load_levels
166 do
167 # Transform level strings into level objects. */
168 for i in [0..levels_code.length[ do
169 var l = new Level(self,i, levels_code[i])
170 levels[i] = l
171 end
172 end
173
174 # The current played level (if any)
175 var level: nullable Level = null
176
177 init
178 do
179 load_levels
180 end
181 end
182