1 /* Tower Toppler - Nebulus
2  * Copyright (C) 2000-2012  Andreas R�ver
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8 
9  * This program 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.
13 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 
19 #include "elevators.h"
20 
21 #include "level.h"
22 #include "decl.h"
23 #include "toppler.h"
24 
25 #include <stdlib.h>
26 
27 #define MAX_ELE 10
28 
29 /* elevators are handled in a quite complicated way: while
30  the toppler is moving on the elevator the platform is invisible
31  and drawn together with the toppler. The stick below the elevator
32  is always drawn in such a way that the last one will appear or disappear
33  below the platform under the toppler */
34 
35 static struct {
36   /* the current position of the platform */
37   Uint8 angle;
38   Uint16 vertical;
39 
40   /* time until the elevator falls down */
41   Sint8 time;
42 
43   /* background value necessary because in between the stations it
44    is impossible to show a platform so we save the actual value
45    there and force a station at the position, when the elevator moves
46    further down we restore the value there */
47   Uint8 bg;
48 } elevators[MAX_ELE];
49 
50 static Sint8 active_ele;
51 static Sint8 ele_dir;
52 
ele_init(void)53 void ele_init(void) {
54 
55   for (Uint8 t = 0; t < MAX_ELE; t++)
56     elevators[t].time = -1;
57 
58   active_ele = -1;
59 }
60 
ele_select(Uint16 row,Uint8 col)61 void ele_select(Uint16 row, Uint8 col) {
62 
63   assert_msg(active_ele == -1, "Select more than one elevator.");
64 
65   Uint8 what = 0;
66 
67   col /= 8;
68   row /= 4;
69   row--;
70 
71   for (int t = 0; t < MAX_ELE; t++) {
72     if ((elevators[t].time == -1) && (what == 0)) {
73       what = 1;
74       active_ele = t;
75     }
76     if ((elevators[t].angle == col) && (elevators[t].vertical == row)) {
77       what = 2;
78       active_ele = t;
79     }
80   }
81 
82   elevators[active_ele].angle = col;
83   elevators[active_ele].vertical = row;
84   elevators[active_ele].time = -1;
85 
86 }
87 
ele_activate(Sint8 dir)88 void ele_activate(Sint8 dir) {
89 
90   assert_msg(active_ele != -1, "Work with unselected elevator, activate.");
91 
92   lev_platform2stick(elevators[active_ele].vertical, elevators[active_ele].angle);
93   ele_dir = dir;
94   if (dir == -1) ele_move();
95 }
96 
ele_move(void)97 void ele_move(void) {
98 
99   assert_msg(active_ele != -1, "Work with unselected elevator, move.");
100 
101   if (ele_dir == 1) {
102     elevators[active_ele].vertical++;
103 
104     lev_empty2stick(elevators[active_ele].vertical, elevators[active_ele].angle);
105   } else {
106     lev_stick2empty(elevators[active_ele].vertical, elevators[active_ele].angle);
107 
108     elevators[active_ele].vertical--;
109   }
110 }
111 
ele_is_atstop(void)112 bool ele_is_atstop(void) {
113 
114   assert_msg(active_ele != -1, "Work with unselected elevator, is_atstop.");
115 
116   if (ele_dir == 1)
117     return lev_is_station(elevators[active_ele].vertical + 1, elevators[active_ele].angle);
118   else
119     return lev_is_station(elevators[active_ele].vertical, elevators[active_ele].angle);
120 }
121 
ele_deactivate(void)122 void ele_deactivate(void) {
123 
124   assert_msg(active_ele != -1, "Deselected an inactive elevator.");
125 
126   if (ele_dir == 1) ele_move();
127 
128   lev_stick2platform(elevators[active_ele].vertical, elevators[active_ele].angle);
129 
130   Uint8 ae = active_ele;
131   active_ele = -1;
132 
133   if (!lev_is_station(elevators[ae].vertical, elevators[ae].angle))
134     elevators[ae].bg = lev_putplatform(elevators[ae].vertical, elevators[ae].angle);
135   else
136     if (lev_is_bottom_station(elevators[ae].vertical, elevators[ae].angle))
137       return;
138     else
139       elevators[ae].bg = lev_tower(elevators[ae].vertical, elevators[ae].angle);
140 
141   elevators[ae].time = 0x7d;
142 }
143 
ele_update(void)144 void ele_update(void) {
145 
146   for (Uint8 t = 0; t < MAX_ELE; t++) {
147     if (elevators[t].time == 0) {
148       lev_restore(elevators[t].vertical, elevators[t].angle, elevators[t].bg);
149       lev_platform2empty(elevators[t].vertical, elevators[t].angle);
150       elevators[t].vertical--;
151       lev_stick2platform(elevators[t].vertical, elevators[t].angle);
152       if (lev_is_bottom_station(elevators[t].vertical, elevators[t].angle)) {
153         elevators[t].time = -1;
154         top_sidemove();
155       } else
156         elevators[t].bg = lev_putplatform(elevators[t].vertical, elevators[t].angle);
157     }
158 
159     if (elevators[t].time > 0)
160       elevators[t].time--;
161   }
162 }
163 
164