3 * Daniel Nelson - 8/24/0
5 * Copyright (C) 2000 Daniel Nelson
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Daniel Nelson - aluminumangel.org
32 #include "Displayer.h"
33 #include "Communicator.h"
35 #define LL_NUMBER_LEVEL_LIGHTS (GC_SAFE_HEIGHT - 1)
38 #define LL_LOCAL_LIGHTS (0)
39 #define LL_OPPONENT_LIGHTS (1)
42 #define LS_RED (1 << 0)
43 #define LS_BLUE (1 << 1)
44 #define LS_FADE_TO_RED (1 << 2)
45 #define LS_FADE_TO_BLUE (1 << 3)
46 #define LS_IMPACT_FLASH (1 << 4)
48 // communication buffer states
49 #define LC_BLUE (1 << 0)
50 #define LC_IMPACT (1 << 1)
51 #define LC_DEATH_FLASH_MASK (1 << (2 * LL_NUMBER_LEVEL_LIGHTS))
60 /* static */ class LevelLights
{
62 static void initialize ( );
63 static void gameStart ( );
64 static void timeStep ( );
66 static inline void levelRaise ( int top_effective_row
)
69 if (top_effective_row
>= LL_NUMBER_LEVEL_LIGHTS
)
70 top_effective_row
= LL_NUMBER_LEVEL_LIGHTS
- 1;
72 while (top_effective_row
>= 0) {
73 LevelLight
&light
= lights
[LL_LOCAL_LIGHTS
][top_effective_row
];
74 if (light
.state
& (LS_RED
| LS_FADE_TO_RED
)) break;
80 static inline void levelLower ( int top_effective_row
)
82 while (top_effective_row
< LL_NUMBER_LEVEL_LIGHTS
) {
83 LevelLight
&light
= lights
[LL_LOCAL_LIGHTS
][top_effective_row
];
84 if (light
.state
& (LS_BLUE
| LS_FADE_TO_BLUE
)) break;
90 static inline void notifyImpact ( int y
, int height
)
92 if (y
- 1 + height
> LL_NUMBER_LEVEL_LIGHTS
) {
93 height
= LL_NUMBER_LEVEL_LIGHTS
- y
+ 1;
94 if (height
< 1) return;
98 LevelLight
&light
= lights
[LL_LOCAL_LIGHTS
][y
- 1 + height
];
99 Communicator::setLevelLightSendBit(LC_IMPACT
<< (2 * (y
- 1 + height
)));
104 static inline void notifySafeHeightViolation ( )
106 if (death_flash_alarm
[LL_LOCAL_LIGHTS
] == -1)
107 death_flash_alarm
[LL_LOCAL_LIGHTS
] = DC_LEVEL_LIGHT_DEATH_FLASH_TIME
;
110 static inline void readySendBuffer ( )
112 for (int n
= LL_NUMBER_LEVEL_LIGHTS
; n
--; )
113 if (lights
[LL_LOCAL_LIGHTS
][n
].state
& (LS_BLUE
| LS_FADE_TO_BLUE
))
114 Communicator::setLevelLightSendBit(LC_BLUE
<< (2 * n
));
116 if (death_flash_alarm
[LL_LOCAL_LIGHTS
] != -1)
117 Communicator::setLevelLightSendBit(LC_DEATH_FLASH_MASK
);
120 static inline void handleRecvBuffer ( )
122 if (Communicator::checkLevelLightRecvBit(LC_DEATH_FLASH_MASK
)
123 && death_flash_alarm
[LL_OPPONENT_LIGHTS
] == -1)
124 death_flash_alarm
[LL_OPPONENT_LIGHTS
] = DC_LEVEL_LIGHT_DEATH_FLASH_TIME
;
126 for (int n
= LL_NUMBER_LEVEL_LIGHTS
; n
--; ) {
127 if (lights
[LL_OPPONENT_LIGHTS
][n
].state
& (LS_RED
| LS_FADE_TO_RED
)) {
128 if (Communicator::checkLevelLightRecvBit(LC_BLUE
<< (2 * n
)))
129 setBlue(lights
[LL_OPPONENT_LIGHTS
][n
]);
131 if (!Communicator::checkLevelLightRecvBit(LC_BLUE
<< (2 * n
)))
132 setRed(lights
[LL_OPPONENT_LIGHTS
][n
]);
135 if (Communicator::checkLevelLightRecvBit(LC_IMPACT
<< (2 * n
)))
136 setFlashing(lights
[LL_OPPONENT_LIGHTS
][n
]);
140 // level light n corresponds to row n + 1 in the grid
141 static LevelLight lights
[2][LL_NUMBER_LEVEL_LIGHTS
];
143 static int death_flash_alarm
[2];
146 static inline void setBlue ( LevelLight
&light
)
148 if (light
.state
& LS_FADE_TO_RED
)
149 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
- light
.fade_alarm
;
151 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
;
152 light
.state
&= ~(LS_RED
| LS_FADE_TO_RED
);
153 light
.state
|= LS_FADE_TO_BLUE
;
156 static inline void setRed ( LevelLight
&light
)
158 if (light
.state
& LS_FADE_TO_BLUE
)
159 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
- light
.fade_alarm
;
161 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
;
162 light
.state
&= ~(LS_BLUE
| LS_FADE_TO_BLUE
);
163 light
.state
|= LS_FADE_TO_RED
;
166 static inline void setFlashing ( LevelLight
&light
)
168 if (light
.state
& LS_IMPACT_FLASH
) {
169 // if past flash inflection point, sync flash start
170 if (light
.flash_alarm
< (int) (DC_LEVEL_LIGHT_FLASH_INFLECTION
171 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
))
172 light
.flash_alarm
= (int) (DC_LEVEL_LIGHT_FLASH_INFLECTION
173 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
)
174 + (int) (((1.0f
- DC_LEVEL_LIGHT_FLASH_INFLECTION
)
175 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
) * (1.0f
176 - light
.flash_alarm
* (1.0f
/ (DC_LEVEL_LIGHT_FLASH_INFLECTION
177 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
))));
180 light
.state
|= LS_IMPACT_FLASH
;
181 light
.flash_alarm
= DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
;