2 This file is part of POCA - a puzzle game
4 POCA is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This software is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>.
20 function secrets_big(bigx
, bigy
)
21 current
.painting
= false -- done automatically if pencil
22 big_playfield
.selectedx
, big_playfield
.selectedy
= bigx
, bigy
26 -- an unique number that depends on direction and current level
27 function secrets_arrow_number(dx
, dy
)
29 for a
= 1, #directions
do
30 if (dx
== directions
[a
][1]) and (dy
== directions
[a
][2]) then
31 direction
= a
- 1 / 2 -- 0 to 3
34 local slevel
= game
.currentlevel
- level_labels
['Secrets'] -- 0 to 15
35 return slevel
+ direction
* 16
39 -- click on secrets arrow
40 -- check death or go immediately if already used
41 function secrets_arrow(dx
, dy
)
42 local function secrets_go(dx
, dy
)
43 local newx
= big_playfield
.selectedx
+ dx
44 local newy
= big_playfield
.selectedy
+ dy
45 if newx
< 1 or newx
> 4 or newy
< 1 or newy
> 4 then
46 newx
= big_playfield
.selectedx
47 newy
= big_playfield
.selectedy
50 return level_labels
['Secrets'] + newx
- 1 + (newy
- 1) * 4
52 local san
= secrets_arrow_number(dx
, dy
)
53 -- if diagonal or used
54 if (dx
~= 0 and dy
~= 0) or game
.secrets_arrows_used
[san
] then
55 fade_to_level(secrets_go(dx
, dy
)) -- go immediately
57 playfield
.goto
= {secrets_go(dx
, dy
), san
} -- go if player survives
62 -- show arrows hidden in gifts, if already used
63 function secrets_check_gifts()
64 if not level_labels
[game
.currentlevel
] == 'Secrets' then return end
65 inplayfield(function (x
, y
, p
) if p
.gift
then
66 local tile
= recognizeink(p
.gift
)
67 if (tile
.kind
== 'secrets_arrow') and tile
.used
then
68 playfield
[x
][y
].contains
= tile
69 playfield
[x
][y
].used
= tile
.used
70 playfield
[x
][y
].onclick
= tile
.onclick
76 function paint_mode(x
, y
)
77 -- cycles through paint modes
79 if not playfield
.paint_mode
then playfield
.paint_mode
= 0 end
80 playfield
.paint_mode
= (playfield
.paint_mode
+ 1) % 4
81 if playfield
.paint_mode
== 0 then playfield
.paint_mode
= nil end
83 -- ... or sets a pixel
85 if not game
.painted_levels
[game
.currentlevel
] then
86 game
.painted_levels
[game
.currentlevel
] = {}
88 local pl
= game
.painted_levels
[game
.currentlevel
]
90 if pl
[x
][y
] == playfield
.paint_mode
then
93 pl
[x
][y
] = playfield
.paint_mode
100 -- paints level_colors (4x4 canvas) according to game.painted.levels[currentlevel]
101 function paint_level()
102 if not level_colors
then
103 level_colors
= love
.graphics
.newCanvas(4, 4)
104 level_colors
:setFilter('linear', 'linear')
106 level_colors
:renderTo(love
.graphics
.clear
)
108 local pl
= game
.painted_levels
[game
.currentlevel
]
109 if not pl
then return end
110 inplayfield(function (x
, y
, p
)
112 if pl
[x
] then mode
= pl
[x
][y
] end
114 love
.graphics
.setColor(0,1,0, .5)
115 elseif mode
== 2 then
116 love
.graphics
.setColor(1,0,0, .5)
117 elseif mode
== 3 then
118 love
.graphics
.setColor(1,1,0, .5)
120 love
.graphics
.setColor(0,0,0, 0)
122 love
.graphics
.setCanvas(level_colors
)
123 love
.graphics
.setPointSize(1)
124 love
.graphics
.setBlendMode('replace')
125 love
.graphics
.points(x
- .5 , y
- .5) -- should be on center of square
126 love
.graphics
.setBlendMode('alpha')
127 love
.graphics
.setCanvas()
132 -- mark arrows according to their colors
133 function auto_paint()
134 local function get_mode(text
)
135 if text
== 'green' then return 1 end
136 if text
== 'red' then return 2 end
137 if text
== 'yellow' then return 3 end
139 game
.painted_levels
[game
.currentlevel
] = {}
140 inplayfield(function(x
, y
, p
)
141 local mode
= get_mode(p
.kind
)
143 game
.painted_levels
[game
.currentlevel
][x
] =
144 game
.painted_levels
[game
.currentlevel
][x
] or {}
145 game
.painted_levels
[game
.currentlevel
][x
][y
] = mode
152 function setup_wise_man_battle()
153 game
.painted_levels
[game
.currentlevel
] = nil
155 if game
.solved_levels
[game
.currentlevel
] then return end
156 if not game
.wisepuzzle
then
157 inplayfield(function (x
, y
, p
)
158 p
.onclick
= function ()
159 change_screen('story_battle')
160 playfield
.clickedx
, playfield
.clickedy
= nil, nil
161 current
.phase
= nil -- will reset to play
163 if p
.kind
== 'wiseman' then
164 playfield
.wisemanx
, playfield
.wisemany
= x
, y
167 else -- puzzle finished
168 game
.solved_levels
[game
.currentlevel
] = true
169 game
.wisepuzzle
= false
170 game
.shuffled
= false
171 inplayfield(function (x
, y
, p
)
172 if p
.kind
== 'wiseman' then
173 playfield
[x
][y
] = recognizeink('D')
180 function start_wise_man_battle()
181 inplayfield(function (x
, y
, p
) p
.onclick
= nil end)
182 playfield
[playfield
.wisemanx
][playfield
.wisemany
].onclick
= function ()
184 current
.showkill
= true
187 current
.symbolic
= true
189 local wisemix
= random_list(16)
190 local pl
= game
.painted_levels
[game
.currentlevel
]
191 local plnew
= { {}, {}, {}, {} }
192 game
.shuffled
= { {}, {}, {}, {} }
193 for x
= 1, 4 do for y
= 1, 4 do
194 local a
= x
+ (y
- 1) * 4
195 game
.shuffled
[x
][y
] = {}
196 local rx
= (wisemix
[a
] - 1) % 4 + 1
197 local ry
= math
.floor((wisemix
[a
] - 1) / 4) + 1
198 game
.shuffled
[x
][y
].x
= rx
199 game
.shuffled
[x
][y
].y
= ry
200 if pl
and pl
[x
] and pl
[x
][y
] then plnew
[rx
][ry
] = pl
[x
][y
] end
202 game
.painted_levels
[game
.currentlevel
] = plnew
204 change_screen('playfield')
208 function start_wise_man_puzzle()
209 inplayfield(function (x
, y
, p
) playfield
[x
][y
] = recognizeink() end)
210 playfield
.clickedx
, playfield
.clickedy
= nil, nil
211 playfield
.wisemanx
, playfield
.wisemany
= nil, nil
212 game
.painted_levels
[game
.currentlevel
] = nil
217 function setup_big_death()
218 playfield
= small_playfield
220 setup_big_playfield()
222 current
.phase
= 'play'
223 change_screen('story_big_death')
224 screen
.minimap
:renderTo(draw_minimap
)
229 if e
== 'pill on' then
230 game
.underpill
= true
231 setuplevel(level_labels
['Knockout'])
232 elseif e
== 'pill off' then
233 game
.underpill
= false
235 setuplevel(level_labels
['Genie'])
236 elseif e
== 'devil on' then
243 -- replaces functions from the main game
244 -- old functions are saved as rr.old_xx
245 function hijack(mini
)
246 local h
= mini
.hijacked_love_functions
248 mini
['old_' .. h
[a]]
= love
[h
[a]]
249 love
[h
[a]]
= mini
[h
[a]]
251 local h
= mini
.hijacked_globals
252 if not h
then return end
254 mini
['old_' .. h
[a]]
= _G
[h
[a]]
255 _G
[h
[a]]
= mini
[h
[a]]
260 -- restore hijacked functions and globals
261 function release(mini
)
262 local h
= mini
.hijacked_love_functions
264 love
[h
[a]]
= mini
['old_' .. h
[a]]
266 local h
= mini
.hijacked_globals
267 if not h
then return end
269 _G
[h
[a]]
= mini
['old_' .. h
[a]]
274 -- get 3 random objects from wise_man_has
275 -- exclude the last one (just donated)
276 function wise_get_offer()
277 local wmh
= game
.wise_man_has
278 local r
= random_list(#game
.wise_man_has
- 1)
279 return { wmh
[r
[1]]
, wmh
[r
[2]]
, wmh
[r
[3]]
}
283 -- remove an item from wise man's inventory
284 -- preserve order, as last item is recently donated and won't be offered
285 function wise_man_lose(trinket_name
)
286 local wmh
= game
.wise_man_has
289 lost
= lost
or (wmh
[a
] == trinket_name
)
290 if lost
then game
.wise_man_has
[a
] = wmh
[a
+ 1] end
296 advice_yellow
= {'advice on turning yellow arrows', 'There is a genie in the red box, that makes yellow arrows turn by themselves. It never rotates the same arrow twice in a row.'},
297 advice_genie
= {'advice on stopping yellow arrows', 'To get rid of the genie, you\'d have to go back in time, helped by a pill.'},
298 advice_pill
= {'advice on the location of the pill', 'There is a pill at the very end of this road, locked by purple arrows.'},
299 advice_purple
= {'advice on the behavior of purple arrows', 'All purple arrows turn as one. To make a lasting change, seek places with odd number of purple arrows!'},
300 advice_map
= {'story of the map', 'Long ago I created a map of this area. It shows passages, gates and where to unlock them. But I traded it with a certain explorer. Should you meet him, ask him about it!'},
301 advice_boxes
= {'advice on the behavior of boxes', 'If you leave boxes alone, they will open at the end of the level. Otherwise, they will just disappear. Such it is also in life. Too strong a wish becomes an obstacle towards what you seek.'},
305 function draw_title()
306 local t
= screen
.tilesize
308 hatch
:send('line_transparency', .7)
309 love
.graphics
.setShader(hatch
)
310 inplayfield(function (x
, y
, p
)
311 draw_floor(x
- .5, y
- .5)
313 playfield
= big_playfield
314 inplayfield(function (x
, y
, p
)
315 draw_image(p
, x
- .5, y
- .5)
317 playfield
= small_playfield
318 love
.graphics
.setShader()
319 draw_image({name
= 'po'}, 1.5, 0.5)
320 draw_image({name
= 'ca'}, 1.5, 1.5)
321 draw_image({name
= 'version'}, 2.5, 2.5)
322 love
.graphics
.setColor(1, 1, 1)
323 --love.graphics.rectangle('fill', t * 2 + tt , t * 3 + tt, t - 2 * tt, t- 2 * tt)
324 --love.graphics.setColor(.4, .4, .4)
325 love
.graphics
.printf('path of colored arrows',
326 t
* 2, t
* 3 + (t
- 3 * screen
.fontheight
) / 2,
329 love
.graphics
.setColor(1, 1, 1)