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
31 #include "Displayer.h"
32 #include "Communicator.h"
34 #define LL_NUMBER_LEVEL_LIGHTS (GC_SAFE_HEIGHT - 1)
37 #define LL_LOCAL_LIGHTS (0)
38 #define LL_OPPONENT_LIGHTS (1)
41 #define LS_RED (1 << 0)
42 #define LS_BLUE (1 << 1)
43 #define LS_FADE_TO_RED (1 << 2)
44 #define LS_FADE_TO_BLUE (1 << 3)
45 #define LS_IMPACT_FLASH (1 << 4)
47 // communication buffer states
48 #define LC_BLUE (1 << 0)
49 #define LC_IMPACT (1 << 1)
50 #define LC_DEATH_FLASH_MASK (1 << (2 * LL_NUMBER_LEVEL_LIGHTS))
59 /* static */ class LevelLights
{
61 static void initialize ( );
62 static void gameStart ( );
63 static void timeStep ( );
65 static inline void levelRaise ( int top_effective_row
)
68 if (top_effective_row
>= LL_NUMBER_LEVEL_LIGHTS
)
69 top_effective_row
= LL_NUMBER_LEVEL_LIGHTS
- 1;
71 while (top_effective_row
>= 0) {
72 LevelLight
&light
= lights
[LL_LOCAL_LIGHTS
][top_effective_row
];
73 if (light
.state
& (LS_RED
| LS_FADE_TO_RED
)) break;
79 static inline void levelLower ( int top_effective_row
)
81 while (top_effective_row
< LL_NUMBER_LEVEL_LIGHTS
) {
82 LevelLight
&light
= lights
[LL_LOCAL_LIGHTS
][top_effective_row
];
83 if (light
.state
& (LS_BLUE
| LS_FADE_TO_BLUE
)) break;
89 static inline void notifyImpact ( int y
, int height
)
91 if (y
- 1 + height
> LL_NUMBER_LEVEL_LIGHTS
) {
92 height
= LL_NUMBER_LEVEL_LIGHTS
- y
+ 1;
93 if (height
< 1) return;
97 LevelLight
&light
= lights
[LL_LOCAL_LIGHTS
][y
- 1 + height
];
98 Communicator::setLevelLightSendBit(LC_IMPACT
<< (2 * (y
- 1 + height
)));
103 static inline void notifySafeHeightViolation ( )
105 if (death_flash_alarm
[LL_LOCAL_LIGHTS
] == -1)
106 death_flash_alarm
[LL_LOCAL_LIGHTS
] = DC_LEVEL_LIGHT_DEATH_FLASH_TIME
;
109 static inline void readySendBuffer ( )
111 for (int n
= LL_NUMBER_LEVEL_LIGHTS
; n
--; )
112 if (lights
[LL_LOCAL_LIGHTS
][n
].state
& (LS_BLUE
| LS_FADE_TO_BLUE
))
113 Communicator::setLevelLightSendBit(LC_BLUE
<< (2 * n
));
115 if (death_flash_alarm
[LL_LOCAL_LIGHTS
] != -1)
116 Communicator::setLevelLightSendBit(LC_DEATH_FLASH_MASK
);
119 static inline void handleRecvBuffer ( )
121 if (Communicator::checkLevelLightRecvBit(LC_DEATH_FLASH_MASK
)
122 && death_flash_alarm
[LL_OPPONENT_LIGHTS
] == -1)
123 death_flash_alarm
[LL_OPPONENT_LIGHTS
] = DC_LEVEL_LIGHT_DEATH_FLASH_TIME
;
125 for (int n
= LL_NUMBER_LEVEL_LIGHTS
; n
--; ) {
126 if (lights
[LL_OPPONENT_LIGHTS
][n
].state
& (LS_RED
| LS_FADE_TO_RED
)) {
127 if (Communicator::checkLevelLightRecvBit(LC_BLUE
<< (2 * n
)))
128 setBlue(lights
[LL_OPPONENT_LIGHTS
][n
]);
130 if (!Communicator::checkLevelLightRecvBit(LC_BLUE
<< (2 * n
)))
131 setRed(lights
[LL_OPPONENT_LIGHTS
][n
]);
134 if (Communicator::checkLevelLightRecvBit(LC_IMPACT
<< (2 * n
)))
135 setFlashing(lights
[LL_OPPONENT_LIGHTS
][n
]);
139 static void handleAI ();
141 // level light n corresponds to row n + 1 in the grid
142 static LevelLight lights
[2][LL_NUMBER_LEVEL_LIGHTS
];
144 static int death_flash_alarm
[2];
147 static inline void setBlue ( LevelLight
&light
)
149 if (light
.state
& LS_FADE_TO_RED
)
150 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
- light
.fade_alarm
;
152 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
;
153 light
.state
&= ~(LS_RED
| LS_FADE_TO_RED
);
154 light
.state
|= LS_FADE_TO_BLUE
;
157 static inline void setRed ( LevelLight
&light
)
159 if (light
.state
& LS_FADE_TO_BLUE
)
160 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
- light
.fade_alarm
;
162 light
.fade_alarm
= DC_LEVEL_LIGHT_FADE_TIME
;
163 light
.state
&= ~(LS_BLUE
| LS_FADE_TO_BLUE
);
164 light
.state
|= LS_FADE_TO_RED
;
167 static inline void setFlashing ( LevelLight
&light
)
169 if (light
.state
& LS_IMPACT_FLASH
) {
170 // if past flash inflection point, sync flash start
171 if (light
.flash_alarm
< (int) (DC_LEVEL_LIGHT_FLASH_INFLECTION
172 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
))
173 light
.flash_alarm
= (int) (DC_LEVEL_LIGHT_FLASH_INFLECTION
174 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
)
175 + (int) (((1.0f
- DC_LEVEL_LIGHT_FLASH_INFLECTION
)
176 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
) * (1.0f
177 - light
.flash_alarm
* (1.0f
/ (DC_LEVEL_LIGHT_FLASH_INFLECTION
178 * DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
))));
181 light
.state
|= LS_IMPACT_FLASH
;
182 light
.flash_alarm
= DC_LEVEL_LIGHT_IMPACT_FLASH_TIME
;