+#include "snake.qh"
REGISTER_MINIGAME(snake, "Snake"); // SNAAAAKE
const float SNAKE_TURN_MOVE = 0x0100; // the snake is moving, player must control it
.float snake_delay;
.vector snake_dir;
+.entity snake_next, snake_last, snake_prev;
+
.bool snake_tail;
-.int snake_lives;
+.int snake_lives[SNAKE_TEAMS + 1];
.int snake_lost_teams;
bool snake_alone(entity minig)
{
int headcount = 0;
- entity e = world;
+ entity e = NULL;
while ( ( e = findentity(e,owner,minig) ) )
if ( e.classname == "minigame_board_piece" && e.cnt == 1 )
++headcount;
// find same game piece given its tile name
entity snake_find_piece(entity minig, string tile)
{
- entity e = world;
+ entity e = NULL;
while ( ( e = findentity(e,owner,minig) ) )
if ( e.classname == "minigame_board_piece" && e.netname == tile )
return e;
- return world;
+ return NULL;
}
// find same game piece given its cnt
entity snake_find_cnt(entity minig, int steam, int tile)
{
- entity e = world;
+ entity e = NULL;
while ( ( e = findentity(e,owner,minig) ) )
if ( e.classname == "minigame_board_piece" && e.cnt == tile && e.team == steam )
return e;
- return world;
+ return NULL;
}
// check if the tile name is valid (15x15 grid)
entity snake_find_head(entity minig, int steam)
{
- entity e = world;
+ entity e = NULL;
while ( ( e = findentity(e,owner,minig) ) )
if ( e.classname == "minigame_board_piece" && e.cnt == 1 && e.team == steam )
return e;
- return world;
+ return NULL;
}
void snake_new_mouse(entity minigame)
{
string pos = minigame_tile_buildname(i, j);
if(!snake_find_piece(minigame, pos))
- RandomSelection_Add(world, 0, pos, 1, 1);
+ RandomSelection_AddString(pos, 1, 1);
}
entity piece = msle_spawn(minigame,"minigame_board_piece");
for(int i = 1; i <= SNAKE_TEAMS; ++i)
{
entity pl = snake_get_player(minigame, i);
- if(pl)
- if(pl.snake_lives > 0)
+ if(pl && minigame.snake_lives[i] > 0)
{
if(winning_team)
return 0;
- winning_team = pl.team;
+ winning_team = i;
}
}
for(int i = 1; i <= SNAKE_TEAMS; ++i)
{
entity pl = snake_get_player(minigame, i);
- if(pl)
- if(pl.snake_lives > 0)
+ if(pl && minigame.snake_lives[i] > 0)
++alivecnt;
}
}
void snake_move_head(entity minigame, entity head);
-void snake_head_think()
+void snake_head_think(entity this)
{
- entity minigame = self.owner;
+ entity minigame = this.owner;
if(minigame.minigame_flags & SNAKE_TURN_MOVE)
- snake_move_head(minigame, self);
+ snake_move_head(minigame, this);
snake_check_winner(minigame);
- self.nextthink = time + self.snake_delay;
+ this.nextthink = time + this.snake_delay;
}
void minigame_setup_snake(entity minigame, int pteam)
{
string pos = minigame_tile_buildname(i, j);
if(!snake_find_piece(minigame, pos))
- RandomSelection_Add(world, 0, pos, 1, 1);
+ RandomSelection_AddString(pos, 1, 1);
}
entity piece = msle_spawn(minigame,"minigame_board_piece");
piece.team = pteam;
piece.netname = strzone(RandomSelection_chosen_string);
piece.cnt = 1;
- piece.think = snake_head_think;
+ piece.snake_next = NULL;
+ piece.snake_prev = NULL;
+ piece.snake_last = piece;
+ setthink(piece, snake_head_think);
piece.snake_delay = autocvar_sv_minigames_snake_delay_initial;
piece.nextthink = time + 0.1;
minigame_server_sendflags(piece,MINIG_SF_ALL);
#ifdef SVQC
for(e = minigame.minigame_players; e; e = e.list_next)
#elif defined(CSQC)
- e = world;
+ e = NULL;
while( (e = findentity(e,owner,minigame)) )
if ( e.classname == "minigame_player" )
#endif
if(e.team == pteam)
return e;
- return world;
+ return NULL;
}
-void snake_add_score(entity minigame, int pteam, .int score_field, int thescore)
+void snake_add_score(entity minigame, int pteam, int thescore)
{
#ifdef SVQC
if(!minigame)
entity pl = snake_get_player(minigame, pteam);
if(pl)
{
- pl.score_field += thescore;
+ pl.snake_score += thescore;
pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
}
#endif
void snake_move_body(entity minigame, entity head, bool ate_mouse)
{
- entity tail = world;
- string tailpos = string_null;
- vector taildir = '0 0 0';
-
- int i, pieces = 0;
- for(i = (SNAKE_NUM_CNT * SNAKE_LET_CNT); i >= 2; --i)
+ for(entity e = head.snake_last; e; e = e.snake_prev)
{
- entity piece = snake_find_cnt(minigame, head.team, i);
- entity nextpiece = snake_find_cnt(minigame, head.team, i - 1);
- if(!piece)
- continue;
+ if(!e || e == head) { break; }
- pieces++;
+ entity nextpiece = e.snake_prev; // can be head
- if(!tail)
- {
- tail = piece;
- tailpos = piece.netname;
- taildir = piece.snake_dir;
- }
-
- if(piece.netname) { strunzone(piece.netname); }
- piece.netname = strzone(nextpiece.netname);
- piece.snake_dir = nextpiece.snake_dir;
- minigame_server_sendflags(piece, MINIG_SF_ALL);
+ if(e.netname) { strunzone(e.netname); }
+ e.netname = strzone(nextpiece.netname);
+ e.snake_dir = nextpiece.snake_dir;
+ minigame_server_sendflags(e, MINIG_SF_UPDATE);
}
- // just a head
- if(!pieces)
+ if(ate_mouse)
{
- tail = head;
- tailpos = head.netname;
- taildir = head.snake_dir;
- }
+ entity tail = head.snake_last;
- if(tail && ate_mouse)
- {
tail.snake_tail = false;
int newcnt = tail.cnt + 1;
head.snake_delay = max(autocvar_sv_minigames_snake_delay_min, autocvar_sv_minigames_snake_delay_initial - (newcnt / autocvar_sv_minigames_snake_delay_multiplier));
- snake_add_score(minigame, head.team, snake_score, 1);
+ snake_add_score(minigame, head.team, 1);
entity piece = msle_spawn(minigame,"minigame_board_piece");
piece.cnt = newcnt;
piece.team = head.team;
- piece.snake_dir = taildir;
+ piece.snake_prev = tail;
+ piece.snake_dir = tail.snake_dir;
+ piece.snake_next = NULL;
piece.snake_tail = true;
- piece.netname = strzone(tailpos);
- minigame_server_sendflags(piece,MINIG_SF_ALL);
+ piece.netname = strzone(tail.netname);
- minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ tail.snake_next = piece;
+ head.snake_last = piece;
+
+ minigame_server_sendflags(piece,MINIG_SF_UPDATE);
+
+ //minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
}
}
entity head = snake_find_head(minigame, pteam);
if(!head) { return; }
- snake_add_score(minigame, pteam, snake_lives, -1);
+ minigame.snake_lives[pteam] -= 1;
+
+ entity pl = snake_get_player(minigame, pteam);
+#ifdef SVQC
+ pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+#endif
+
head.nextthink = time + 1; // make sure they don't to eat us somehow
- entity e = world;
+ entity e = NULL;
while ( ( e = findentity(e,owner,minigame) ) )
if ( e.classname == "minigame_board_piece" && e.cnt && e.team == pteam )
{
if(e.netname) { strunzone(e.netname); }
- remove(e);
+ delete(e);
}
- entity pl = snake_get_player(minigame, pteam);
- if(pl.snake_lives > 0)
- minigame_setup_snake(minigame, pteam);
- else
+ if(minigame.snake_lives[pteam] <= 0)
minigame.snake_lost_teams |= BIT(pteam);
+
+ if(pl && minigame.snake_lives[pteam] > 0)
+ minigame_setup_snake(minigame, pteam);
}
void snake_move_head(entity minigame, entity head)
}
else
{
- snake_add_score(minigame, head.team, snake_score, -1);
+ snake_add_score(minigame, head.team, -1);
snake_eat_team(minigame, head.team);
}
if(head.netname) { strunzone(head.netname); }
head.netname = strzone(newpos);
- minigame_server_sendflags(head,MINIG_SF_ALL);
+ minigame_server_sendflags(head,MINIG_SF_UPDATE);
// above check makes sure it's not our team
if(hit.cnt)
{
snake_eat_team(minigame, hit.team);
- snake_add_score(minigame, head.team, snake_score, 1);
+ snake_add_score(minigame, head.team, 1);
}
if(ate_mouse)
{
if(hit.netname) { strunzone(hit.netname); }
- remove(hit);
+ delete(hit);
snake_new_mouse(minigame);
}
snake_setup_pieces(minigame);
minigame.minigame_flags = SNAKE_TURN_MOVE;
minigame.snake_lost_teams = 0;
+
+ if(SNAKE_TEAMS > 1)
+ {
+ for(int i = 1; i <= SNAKE_TEAMS; ++i)
+ minigame.snake_lives[i] = autocvar_sv_minigames_snake_lives;
+ }
+ else
+ minigame.snake_lives[1] = 1;
+
return true;
}
case "end":
{
- entity e = world;
+ entity e = NULL;
while( (e = findentity(e, owner, minigame)) )
if(e.classname == "minigame_board_piece")
{
if(e.netname) { strunzone(e.netname); }
- remove(e);
+ delete(e);
}
return false;
}
entity pl = ...(1,entity);
if(pl)
{
- pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1);
+ //pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1);
+ // send score anyway, lives are set
pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
}
minigame_setup_snake(minigame, t);
{
switch(argv(0))
{
- case "move":
- snake_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) == 3 ? argv(2) : string_null));
+ case "move":
+ snake_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) == 3 ? argv(2) : string_null));
return true;
}
int sf = ...(1,int);
if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
{
+ int letter = minigame_tile_letter(sent.netname);
+ int number = minigame_tile_number(sent.netname);
+
+ WriteByte(MSG_ENTITY,letter);
+ WriteByte(MSG_ENTITY,number);
+
WriteByte(MSG_ENTITY,sent.cnt);
WriteByte(MSG_ENTITY,sent.snake_tail);
- WriteCoord(MSG_ENTITY,sent.snake_dir_x);
- WriteCoord(MSG_ENTITY,sent.snake_dir_y);
+
+ int dx = sent.snake_dir_x;
+ int dy = sent.snake_dir_y;
+ if(dx == -1) dx = 2;
+ if(dy == -1) dy = 2;
+ WriteByte(MSG_ENTITY,dx);
+ WriteByte(MSG_ENTITY,dy);
}
else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
{
WriteLong(MSG_ENTITY,sent.snake_score);
- WriteByte(MSG_ENTITY,max(0, sent.snake_lives));
+ WriteByte(MSG_ENTITY,max(0, minigame.snake_lives[sent.team]));
}
else if ( sent.classname == "minigame" && (sf & MINIG_SF_UPDATE ) )
{
return false;
}
}
-
+
return false;
}
minigame_hud_fitsqare(pos, mySize);
snake_boardpos = pos;
snake_boardsize = mySize;
-
+
minigame_hud_simpleboard(pos,mySize,minigame_texture("snake/board"));
vector tile_size = minigame_hud_denormalize_size('1 1 0' / SNAKE_TILE_SIZE,pos,mySize);
{
int thex = minigame_tile_letter(e.netname);
int they = minigame_tile_number(e.netname);
- entity t = snake_find_cnt(active_minigame, minigame_self.team, e.cnt - 1);
+ entity t = snake_find_cnt(active_minigame, e.team, e.cnt - 1);
int tx = minigame_tile_letter(t.netname);
int ty = minigame_tile_number(t.netname);
}
else
{
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture(thepiece),
tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
}
}
}
- if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (minigame_self.snake_lives <= 0) )
+ if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (active_minigame.snake_lives[minigame_self.team] <= 0) )
{
int scores = minigame_self.snake_score;
if(active_minigame.minigame_flags & SNAKE_TURN_WIN)
if((active_minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
victory_text = "You win!";
- if(minigame_self.snake_lives <= 0)
+ if(active_minigame.snake_lives[minigame_self.team] <= 0)
victory_text = "You ran out of lives!";
-
+
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s %s", victory_text, scores_text),
+ sprintf("%s %s", victory_text, scores_text),
winfs, 0, DRAWFLAG_NORMAL, 0.5);
-
+
drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'0.3 0.3 1',0.8,DRAWFLAG_ADDITIVE);
-
+
minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s %s", victory_text, scores_text),
+ sprintf("%s %s", victory_text, scores_text),
winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
}
}
// Required function, draw the game status panel
void snake_hud_status(vector pos, vector mySize)
{
- HUD_Panel_DrawBg(1);
- vector ts;
- ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
+ HUD_Panel_DrawBg();
+ vector ts = minigame_drawstring_wrapped(mySize.x, pos, active_minigame.descriptor.message,
hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-
- pos_y += ts_y;
- mySize_y -= ts_y;
+ ts.y += hud_fontsize.y;
+ pos.y += ts.y;
+ mySize.y -= ts.y;
vector player_fontsize = hud_fontsize * 1.75;
- ts_y = ( mySize_y - 2*player_fontsize_y ) / SNAKE_TEAMS;
- ts_x = mySize_x;
+ ts.y = player_fontsize.y + (mySize.y - SNAKE_TEAMS * player_fontsize.y) / SNAKE_TEAMS;
+ ts.x = mySize_x;
vector mypos;
- vector tile_size = '48 48 0';
-
- mypos = pos;
- if ( minigame_self.team > 1 )
- mypos_y += player_fontsize_y + (ts_y * (minigame_self.team - 1));
- drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
- mypos_y += player_fontsize_y;
- drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
entity e;
FOREACH_MINIGAME_ENTITY(e)
{
if ( e.classname == "minigame_player" )
{
- mypos = pos;
- if ( e.team > 1 )
- mypos_y += player_fontsize_y + (ts_y * (e.team - 1));
- minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
- player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
- vector tile_color = snake_teamcolor(e.team);
+ mypos = pos + eY * (e.team - 1) * ts.y;
- mypos_y += player_fontsize_y;
- drawpic( mypos,
- minigame_texture("snake/head"),
- tile_size * 0.7, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
-
- mypos_x += tile_size_x;
-
- drawstring(mypos,ftos(e.snake_score),tile_size,
- '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ if (e == minigame_self)
+ {
+ const vector hl_size = '1 1 0';
+ drawfill(mypos + hl_size, ts - 2 * hl_size, snake_teamcolor(e.team), 0.25 * panel_fg_alpha, DRAWFLAG_ADDITIVE);
+ drawborderlines(hl_size.x, mypos + hl_size, ts - 2 * hl_size, snake_teamcolor(e.team), panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+ else
+ drawfill(mypos, ts, snake_teamcolor(e.team), 0.25 * panel_fg_alpha, DRAWFLAG_ADDITIVE);
- mypos_x += tile_size_x;
+ minigame_drawcolorcodedstring_trunc(mySize.x - hud_fontsize.x * 0.5, mypos + eX * hud_fontsize.x * 0.25,
+ entcs_GetName(e.minigame_playerslot - 1),
+ player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring(mypos,strcat("1UP: ", ftos(e.snake_lives)),tile_size * 0.6,
- '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ mypos.y += player_fontsize.y;
+ drawstring_aspect(mypos, ftos(e.snake_score), ts - eY * player_fontsize.y - eX * ts.x * (3 / 4),
+ '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(mypos + eX * ts.x * (1 / 4), strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])), ts - eY * player_fontsize.y - eX * ts.x * (1 / 4),
+ '1 0.44 0.54', panel_fg_alpha, DRAWFLAG_NORMAL);
}
}
}
return _("You win!");
}
- if(minigame_self.snake_lives <= 0)
+ if(active_minigame.snake_lives[minigame_self.team] <= 0)
return _("You ran out of lives!");
-
+
if ( (snake_find_head(active_minigame, minigame_self.team)).snake_dir == '0 0 0' )
return _("Press an arrow key to begin the game");
return _("Avoid the snake's body, collect the mice!");
else
return _("Avoid the screen edges and the snake's body, collect the mice!");
-
+
return "";
}
{
if(sf & MINIG_SF_UPDATE)
{
+ int letter = ReadByte();
+ int number = ReadByte();
+ if(sent.netname) { strunzone(sent.netname); }
+ sent.netname = strzone(minigame_tile_buildname(letter, number));
+
sent.cnt = ReadByte();
sent.snake_tail = ReadByte();
- sent.snake_dir_x = ReadCoord();
- sent.snake_dir_y = ReadCoord();
+
+ int dx = ReadByte();
+ int dy = ReadByte();
+
+ if(dx == 2) dx = -1;
+ if(dy == 2) dy = -1;
+
+ sent.snake_dir_x = dx;
+ sent.snake_dir_y = dy;
sent.snake_dir_z = 0;
}
}
else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
{
sent.snake_score = ReadLong();
- sent.snake_lives = ReadByte();
+ minigame.snake_lives[sent.team] = ReadByte();
}
return false;
return false;
}
-#endif
\ No newline at end of file
+#endif