1 const float PS_TURN_MOVE = 0x0100; // player has to click on a piece on the board
2 const float PS_TURN_WIN = 0x0200; // player has won
3 const float PS_TURN_DRAW = 0x0400; // player can make no more moves
4 const float PS_TURN_TYPE = 0x0f00; // turn type mask
6 const int PS_LET_CNT = 7;
7 const int PS_NUM_CNT = 7;
9 const int PS_TILE_SIZE = 8;
11 // find same game piece given its tile name
12 entity ps_find_piece(entity minig, string tile)
15 while ( ( e = findentity(e,owner,minig) ) )
16 if ( e.classname == "minigame_board_piece" && e.netname == tile )
21 bool ps_draw(entity minigame)
25 while( ( e = findentity(e,owner,minigame) ) )
26 if( e.classname == "minigame_board_piece" )
31 return ((valid > 0) ? true : false);
34 bool ps_tile_blacklisted(string tile)
36 int number = minigame_tile_number(tile);
37 int letter = minigame_tile_letter(tile);
41 else if(number > PS_NUM_CNT - 3)
43 if(letter > PS_LET_CNT - 3)
46 else if(number > PS_NUM_CNT - 3)
52 // check if the tile name is valid (5x5 grid)
53 bool ps_valid_tile(string tile)
57 if(ps_tile_blacklisted(tile))
59 float number = minigame_tile_number(tile);
60 float letter = minigame_tile_letter(tile);
61 return 0 <= number && number < PS_NUM_CNT && 0 <= letter && letter < PS_LET_CNT;
64 // Checks if the given piece completes a row
65 bool ps_winning_piece(entity minigame)
67 //int number = minigame_tile_number(piece.netname);
68 //int letter = minigame_tile_letter(piece.netname);
71 while ( ( e = findentity(e,owner,minigame) ) )
72 if ( e.classname == "minigame_board_piece" )
74 int number = minigame_tile_number(e.netname);
75 int letter = minigame_tile_letter(e.netname);
76 string try = minigame_tile_buildname(letter - 1, number);
77 if(ps_find_piece(minigame,try))
79 try = minigame_tile_buildname(letter - 2, number);
80 if(ps_valid_tile(try) && !ps_find_piece(minigame,try))
81 return false; // a move is valid, abort!
83 try = minigame_tile_buildname(letter + 1, number);
84 if(ps_find_piece(minigame,try))
86 try = minigame_tile_buildname(letter + 2, number);
87 if(ps_valid_tile(try) && !ps_find_piece(minigame,try))
88 return false; // a move is valid, abort!
90 try = minigame_tile_buildname(letter, number - 1);
91 if(ps_find_piece(minigame,try))
93 try = minigame_tile_buildname(letter, number - 2);
94 if(ps_valid_tile(try) && !ps_find_piece(minigame,try))
95 return false; // a move is valid, abort!
97 try = minigame_tile_buildname(letter, number + 1);
98 if(ps_find_piece(minigame,try))
100 try = minigame_tile_buildname(letter, number + 2);
101 if(ps_valid_tile(try) && !ps_find_piece(minigame,try))
102 return false; // a move is valid, abort!
109 void ps_setup_pieces(entity minigame)
112 for(i = 0; i < PS_NUM_CNT; ++i)
113 for(t = 0; t < PS_LET_CNT; ++t)
115 string try = minigame_tile_buildname(i,t);
116 if(!ps_valid_tile(try))
118 if(i == floor(PS_NUM_CNT * 0.5) && t == floor(PS_LET_CNT * 0.5))
119 continue; // middle piece is empty
120 entity piece = msle_spawn(minigame,"minigame_board_piece");
121 piece.team = 1; // init default team?
122 piece.netname = strzone(minigame_tile_buildname(t,i));
123 minigame_server_sendflags(piece,MINIG_SF_ALL);
126 minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
129 bool ps_move_piece(entity minigame, entity piece, string pos, int leti, int numb)
133 if(ps_find_piece(minigame, pos))
135 entity middle = ps_find_piece(minigame, minigame_tile_buildname(leti,numb));
139 if(middle.netname) { strunzone(middle.netname); }
142 if(piece.netname) { strunzone(piece.netname); }
143 piece.netname = strzone(pos);
145 minigame_server_sendflags(piece,MINIG_SF_ALL);
151 void ps_move(entity minigame, entity player, string thepiece, string pos )
153 if ( minigame.minigame_flags & PS_TURN_MOVE )
156 if ( ps_valid_tile(pos) )
157 if ( !ps_find_piece(minigame, pos) && ps_find_piece(minigame, thepiece) )
159 entity piece = ps_find_piece(minigame, thepiece);
160 int number = minigame_tile_number(thepiece);
161 int letter = minigame_tile_letter(thepiece);
165 try = minigame_tile_buildname(letter-1,number);
166 if(ps_find_piece(minigame,try))
168 try = minigame_tile_buildname(letter-2,number);
169 if(ps_valid_tile(try) && try == pos)
170 done = ps_move_piece(minigame, piece, pos, letter - 1, number);
172 try = minigame_tile_buildname(letter+1,number);
173 if(!done && ps_find_piece(minigame,try))
175 try = minigame_tile_buildname(letter+2,number);
176 if(ps_valid_tile(try) && try == pos)
177 done = ps_move_piece(minigame, piece, pos, letter + 1, number);
179 try = minigame_tile_buildname(letter,number-1);
180 if(!done && ps_find_piece(minigame,try))
182 try = minigame_tile_buildname(letter,number-2);
183 if(ps_valid_tile(try) && try == pos)
184 done = ps_move_piece(minigame, piece, pos, letter, number - 1);
186 try = minigame_tile_buildname(letter,number+1);
187 if(!done && ps_find_piece(minigame,try))
189 try = minigame_tile_buildname(letter,number+2);
190 if(ps_valid_tile(try) && try == pos)
191 done = ps_move_piece(minigame, piece, pos, letter, number + 1);
195 return; // didn't make a move
197 minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
199 if ( ps_winning_piece(minigame) )
201 if(ps_draw(minigame))
202 minigame.minigame_flags = PS_TURN_DRAW;
204 minigame.minigame_flags = PS_TURN_WIN;
207 minigame.minigame_flags = PS_TURN_MOVE;
215 // required function, handle server side events
216 int ps_server_event(entity minigame, string event, ...)
222 ps_setup_pieces(minigame);
223 minigame.minigame_flags = PS_TURN_MOVE;
229 while( (e = findentity(e, owner, minigame)) )
230 if(e.classname == "minigame_board_piece")
232 if(e.netname) { strunzone(e.netname); }
239 int pl_num = minigame_count_players(minigame);
241 // Don't allow more than 1 player
242 if(pl_num >= 1) { return false; }
253 ps_move(minigame, ...(0,entity), (...(1,int) == 3 ? argv(1) : string_null), (...(1,int) == 3 ? argv(2) : string_null));
267 entity ps_curr_piece; // identifier for the currently selected piece
268 string ps_curr_pos; // identifier of the tile under the mouse
269 vector ps_boardpos; // HUD board position
270 vector ps_boardsize;// HUD board size
272 // Required function, draw the game board
273 void ps_hud_board(vector pos, vector mySize)
275 minigame_hud_fitsqare(pos, mySize);
277 ps_boardsize = mySize;
279 minigame_hud_simpleboard(pos,mySize,minigame_texture("ps/board"));
281 vector tile_size = minigame_hud_denormalize_size('1 1 0' / PS_TILE_SIZE,pos,mySize);
284 bool valid = ps_valid_tile(ps_curr_pos);
285 bool highlight = false;
289 int number = minigame_tile_number(ps_curr_pos);
290 int letter = minigame_tile_letter(ps_curr_pos);
291 try = minigame_tile_buildname(letter-1,number);
292 if(ps_find_piece(active_minigame,try))
294 try = minigame_tile_buildname(letter-2,number);
295 if(ps_valid_tile(try) && !ps_find_piece(active_minigame,try))
298 try = minigame_tile_buildname(letter+1,number);
299 if(ps_find_piece(active_minigame,try))
301 try = minigame_tile_buildname(letter+2,number);
302 if(ps_valid_tile(try) && !ps_find_piece(active_minigame,try))
305 try = minigame_tile_buildname(letter,number-1);
306 if(ps_find_piece(active_minigame,try))
308 try = minigame_tile_buildname(letter,number-2);
309 if(ps_valid_tile(try) && !ps_find_piece(active_minigame,try))
312 try = minigame_tile_buildname(letter,number+1);
313 if(ps_find_piece(active_minigame,try))
315 try = minigame_tile_buildname(letter,number+2);
316 if(ps_valid_tile(try) && !ps_find_piece(active_minigame,try))
320 bool draw_pos = false;
321 if(ps_curr_piece && valid && !ps_find_piece(active_minigame, ps_curr_pos))
324 int numb = minigame_tile_number(ps_curr_piece.netname);
325 int leti = minigame_tile_letter(ps_curr_piece.netname);
327 try = minigame_tile_buildname(leti-1,numb);
328 if(ps_find_piece(active_minigame,try))
330 try = minigame_tile_buildname(leti-2,numb);
331 if(try == ps_curr_pos)
334 try = minigame_tile_buildname(leti+1,numb);
335 if(ps_find_piece(active_minigame,try))
337 try = minigame_tile_buildname(leti+2,numb);
338 if(try == ps_curr_pos)
341 try = minigame_tile_buildname(leti,numb-1);
342 if(ps_find_piece(active_minigame,try))
344 try = minigame_tile_buildname(leti,numb-2);
345 if(try == ps_curr_pos)
348 try = minigame_tile_buildname(leti,numb+1);
349 if(ps_find_piece(active_minigame,try))
351 try = minigame_tile_buildname(leti,numb+2);
352 if(try == ps_curr_pos)
358 FOREACH_MINIGAME_ENTITY(e)
360 if ( e.classname == "minigame_board_piece" )
362 tile_pos = minigame_tile_pos(e.netname,PS_NUM_CNT,PS_LET_CNT);
363 tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
365 vector tile_color = '1 1 1';
368 if(e.netname == ps_curr_pos)
369 if(ps_curr_piece.netname != ps_curr_pos)
371 minigame_drawpic_centered( tile_pos,
372 minigame_texture("ps/tile_available"),
373 tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
375 if(e == ps_curr_piece)
377 minigame_drawpic_centered( tile_pos,
378 minigame_texture("ps/tile_selected"),
379 tile_size, tile_color, panel_fg_alpha, DRAWFLAG_ADDITIVE );
382 minigame_drawpic_centered( tile_pos,
383 minigame_texture("ps/piece"),
384 tile_size * 0.8, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
390 tile_pos = minigame_tile_pos(ps_curr_pos,PS_NUM_CNT,PS_LET_CNT);
391 tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
393 minigame_drawpic_centered(tile_pos,
394 minigame_texture("ps/piece"),
395 tile_size * 0.8, '0.5 0.5 0.5', panel_fg_alpha, DRAWFLAG_NORMAL);
398 if ( ( active_minigame.minigame_flags & PS_TURN_WIN ) || ( active_minigame.minigame_flags & PS_TURN_DRAW ) )
401 FOREACH_MINIGAME_ENTITY(e)
402 if(e.classname == "minigame_board_piece")
405 vector winfs = hud_fontsize*2;
406 string remaining_text;
407 if(active_minigame.minigame_flags & PS_TURN_WIN)
408 remaining_text = "All pieces cleared!";
410 remaining_text = strcat("Remaining pieces: ", ftos(remaining));
412 vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
414 win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
415 sprintf("Game over! %s", remaining_text),
416 winfs, 0, DRAWFLAG_NORMAL, 0.5);
418 drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
420 minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
421 sprintf("Game over! %s", remaining_text),
422 winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
427 // Required function, draw the game status panel
428 void ps_hud_status(vector pos, vector mySize)
432 ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
433 hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
438 vector player_fontsize = hud_fontsize * 1.75;
439 ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
442 vector tile_size = '48 48 0';
445 drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
446 mypos_y += player_fontsize_y;
447 drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
451 FOREACH_MINIGAME_ENTITY(e)
453 if(e.classname == "minigame_board_piece")
459 FOREACH_MINIGAME_ENTITY(e)
461 if ( e.classname == "minigame_player" )
464 minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
465 GetPlayerName(e.minigame_playerslot-1),
466 player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
468 mypos_y += player_fontsize_y;
470 // minigame_texture("ps/piece"),
471 // tile_size, '1 0 0', panel_fg_alpha, DRAWFLAG_NORMAL );
473 //mypos_x += tile_size_x;
475 drawstring(mypos,sprintf(_("Pieces left: %s"), ftos(remaining)),'28 28 0',
476 '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
481 // Turn a set of flags into a help message
482 string ps_turn_to_string(int turnflags)
484 if (turnflags & PS_TURN_DRAW )
485 return _("No more valid moves");
487 if ( turnflags & PS_TURN_WIN )
488 return _("Well done, you win!");
490 if ( turnflags & PS_TURN_MOVE )
491 return _("Jump a piece over another to capture it");
496 // Make the correct move
497 void ps_make_move(entity minigame)
499 if ( minigame.minigame_flags == PS_TURN_MOVE )
501 entity piece = ps_find_piece(minigame,ps_curr_pos);
502 if(!ps_curr_piece || piece)
503 ps_curr_piece = ps_find_piece(minigame,ps_curr_pos);
506 minigame_cmd("move ", ps_curr_piece.netname, " ", ps_curr_pos);
507 ps_curr_piece = world;
512 void ps_set_curr_pos(string s)
515 strunzone(ps_curr_pos);
521 // Required function, handle client events
522 int ps_client_event(entity minigame, string event, ...)
529 ps_curr_piece = world;
530 minigame.message = ps_turn_to_string(minigame.minigame_flags);
535 //if((minigame.minigame_flags & PS_TURN_TEAM) == minigame_self.team)
537 switch ( ...(0,int) )
540 case K_KP_RIGHTARROW:
542 ps_set_curr_pos("a3");
544 ps_set_curr_pos( minigame_relative_tile(ps_curr_pos,1,0,PS_NUM_CNT,PS_LET_CNT));
549 ps_set_curr_pos("c3");
551 ps_set_curr_pos(minigame_relative_tile(ps_curr_pos,-1,0,PS_NUM_CNT,PS_LET_CNT));
556 ps_set_curr_pos("a1");
558 ps_set_curr_pos(minigame_relative_tile(ps_curr_pos,0,1,PS_NUM_CNT,PS_LET_CNT));
563 ps_set_curr_pos("a3");
565 ps_set_curr_pos(minigame_relative_tile(ps_curr_pos,0,-1,PS_NUM_CNT,PS_LET_CNT));
570 ps_make_move(minigame);
577 case "mouse_pressed":
579 if(...(0,int) == K_MOUSE1)
581 ps_make_move(minigame);
589 vector mouse_pos = minigame_hud_normalize(mousepos,ps_boardpos,ps_boardsize);
590 if ( minigame.minigame_flags == PS_TURN_MOVE )
592 ps_set_curr_pos(minigame_tile_name(mouse_pos,PS_NUM_CNT,PS_LET_CNT));
594 if ( ! ps_valid_tile(ps_curr_pos) )
599 case "network_receive":
601 entity sent = ...(0,entity);
603 if ( sent.classname == "minigame" )
605 if ( sf & MINIG_SF_UPDATE )
607 sent.message = ps_turn_to_string(sent.minigame_flags);
608 if ( sent.minigame_flags & minigame_self.team )