Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

fack.cc

Go to the documentation of this file.
00001 // Copyright 2004, 2005 Maurizio Colucci.
00002 //
00003 // This file is part of FACK. 
00004 //
00005 // FACK is free software; you can redistribute it and/or modify it
00006 // under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // FACK is distributed in the hope that it will be useful, but WITHOUT
00011 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00012 // or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
00013 // License for more details. 
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Foobar; if not, write to the Free Software Foundation,
00017 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018 
00019 #include "fack.hpp"
00020 #include <boost/filesystem/operations.hpp> // includes boost/filesystem/path.hpp
00021 #include <boost/filesystem/fstream.hpp>    // ditto
00022 
00023 #include <SDL/SDL_gfxPrimitives.h>   
00024 
00025 #include <stdio.h>
00026 #include <algorithm>
00027 //#include <math.h> // floor, ceil
00028 
00029 //#define NDEBUG // @@ uncomment this for speedup
00030 #include <assert.h>
00031 
00032 
00033 cfsurf::cfsurf(int apparent_wt_, int apparent_ht_, 
00034     int real_wt_, int real_ht_, int offset_x_, int offset_y_)
00035 {
00036     apparent_wt = apparent_wt_;
00037     apparent_ht = apparent_ht_;
00038     real_wt = real_wt_;
00039     real_ht = real_ht_;
00040     offs_y = offset_y_;
00041     offs_x = offset_x_;
00042     pixels.resize(real_wt_ * real_ht_); 
00043 }
00044 
00045 
00046 
00047 
00048 string string_of_int(int i){
00049     std::ostringstream temp;
00050     temp << i;
00051     return temp.str();
00052 }
00053 
00054 
00055 
00056 void raise_exception(string s){
00057     cerr << s << endl;
00058     throw s;
00059 }
00060 
00061 
00062 bool
00063 point_in_rect(int_pair p, SDL_Rect r)
00064 {
00065     return (r.x <= p.x && p.x<r.x+r.w
00066         &&
00067         r.y <=p.y && p.y <r.y + r.h);
00068 }
00069 
00071 Uint32
00072 get_raw_pixel_32bitpp(SDL_Surface * s, int x, int y)
00073 {
00074     // BEGIN decl
00075     int bpp;
00076     Uint32 * ptr;
00077     SDL_PixelFormat * f;
00078     // END
00079 
00080     // BEGIN precond
00081     if(x >= s->w)
00082         raise_exception("x out of range");
00083     if(y >= s->h){
00084         cerr << " y = " << y << ", ht = " << s->h;
00085         raise_exception(string("get_raw_pixel_32bitpp: y out of range "));}
00086     f = s->format;
00087     bpp = f->BytesPerPixel;
00088     if (bpp != 4){
00089         raise_exception("Only 32 bitpp surfaces supported");}
00090     // END
00091 
00092     ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00093     return * ptr;
00094 
00095 }
00096 
00097 void put_raw_pixel_32bitpp(SDL_Surface * s, int x, int y, Uint32 pixel)
00098 {
00099     // BEGIN decl
00100     int bpp;
00101     Uint32 *p;
00102     // END
00103 
00104     
00105     if(x <= s->w && y <=s->h){//Put pixel only if it is in screen!    
00106         
00107         bpp = s->format->BytesPerPixel;
00108     
00109         if (bpp != 4){
00110             raise_exception("Only 32 bitpp surfaces supported");
00111         }
00112     
00113         p = (Uint32 *)(s->pixels) + x + y * s->w;
00114         *(Uint32 *)p = pixel;
00115     }
00116 }
00117  
00118 
00119 
00120 
00121 inline 
00122 void 
00123 anim_frame::set_pixel(
00124     int x, 
00125     int y, 
00126     rgbaf pix)
00127 {
00128 
00129 
00130     // BEGIN precond
00131     assert(0<= x && x < w);
00132     assert(0<= y && y < h);
00133     // END
00134     pixels[ y * w + x] = pix;
00135 }
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 pt<anim_frame> 
00145 anim_frame::from_sdl_surface(
00146     SDL_Surface * s,
00147     int_pair hot_spot,
00148     float duration)
00149 {
00150     // BEGIN decl
00151     pt<anim_frame> ret;
00152     int x, y;
00153     rgbaf pix;
00154     Uint32 raw_pixel;
00155     Uint32 * ptr;
00156     Uint8 r, g,b, a;
00157     // END
00158 
00159     // BEGIN precond
00160     assert(s != NULL);
00161     assert(s->format->BytesPerPixel == 4);
00162     // END
00163 
00164 
00165     ret = NEW( anim_frame(s->w, s->h, hot_spot, duration));
00166     SDL_LockSurface(s);
00167     for(x = 0; x< s->w ; x++){
00168         for ( y = 0 ; y< s->h ; y++){
00169             ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00170             raw_pixel = * ptr;
00171             SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
00172             ret->set_pixel( x, y, rgbaf_of_rgbai(r, g,b, a));}}
00173     SDL_UnlockSurface(s);
00174     return ret;
00175 }
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 bool surf_and_weight::operator< (const surf_and_weight& s) const{
00184     return this->surf < s.surf;
00185 }
00186 
00187 
00188 
00189 
00190 pt<cfsurf> 
00191 cfsurf::from_sdl_surface(SDL_Surface * s)
00192 {
00193     // BEGIN decl.
00194     pt<cfsurf> surf;
00195     int x, y;
00196     Uint32 raw_pixel;
00197     Uint32 * ptr;
00198     Uint8 r, g, b, a;
00199     rgbaf pix2;
00200     int real_wt, real_ht, offs_x, offs_y, apparent_wt, apparent_ht;
00201     int lowest_nontransparent_x_found_so_far;
00202     int lowest_nontransparent_y_found_so_far;
00203     int highest_nontransparent_x_found_so_far;
00204     int highest_nontransparent_y_found_so_far;
00205     // END
00206 
00207     // BEGIN precond
00208     assert(s != NULL);
00209     assert(s->format->BytesPerPixel == 4);
00210     // END
00211 
00212     lowest_nontransparent_y_found_so_far = INT_MAX;
00213     highest_nontransparent_y_found_so_far = INT_MIN;
00214     lowest_nontransparent_x_found_so_far = INT_MAX;
00215     highest_nontransparent_x_found_so_far = INT_MIN;
00216 
00217     SDL_LockSurface(s);
00218     for ( x = 0; x < s->w; x++)
00219     {
00220         for (y = 0; y < s->h; y++)
00221         {
00222             ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00223             raw_pixel = * ptr;
00224             SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
00225             if (a != 0)
00226             { // not completely transparent
00227                 if (x < lowest_nontransparent_x_found_so_far){
00228                     lowest_nontransparent_x_found_so_far = x;}
00229                 if (x > highest_nontransparent_x_found_so_far){
00230                     highest_nontransparent_x_found_so_far = x;}
00231                 if (y < lowest_nontransparent_y_found_so_far){
00232                     lowest_nontransparent_y_found_so_far = y;}
00233                 if (y > highest_nontransparent_y_found_so_far){
00234                     highest_nontransparent_y_found_so_far = y;}
00235             }
00236         }
00237     }
00238 
00239     assert(lowest_nontransparent_y_found_so_far 
00240         < highest_nontransparent_y_found_so_far);
00241     assert(lowest_nontransparent_x_found_so_far 
00242         < highest_nontransparent_x_found_so_far);
00243 
00244     real_wt = highest_nontransparent_x_found_so_far
00245         - lowest_nontransparent_x_found_so_far;
00246     real_ht = highest_nontransparent_y_found_so_far
00247         - lowest_nontransparent_y_found_so_far;
00248     offs_x = lowest_nontransparent_x_found_so_far;
00249     offs_y = lowest_nontransparent_y_found_so_far;
00250     apparent_ht = s->h;
00251     apparent_wt = s->w;
00252 
00253     surf = NEW( cfsurf(apparent_wt, apparent_ht
00254                     , real_wt, real_ht
00255                     , offs_x, offs_y));
00256     for(x = offs_x; x< offs_x + real_wt; x++){
00257         for ( y = offs_y; y< offs_y + real_ht; y++){
00258             ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00259             raw_pixel = * ptr;
00260             SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
00261             pix2 = rgbaf_of_rgbai(r, g, b, a);
00262             surf->set_pixel( x, y, pix2);}}
00263     SDL_UnlockSurface(s);
00264     return surf;
00265 }
00266 
00267 
00268 
00269 
00270 
00272 int
00273 pow(int base, int exp){
00274     // BEGIN decl
00275     int p;
00276     int count;
00277     // END
00278 
00279     p = 1;
00280     for (count = 0; count< exp; count ++){
00281         p *= base;}
00282     return p;
00283 }
00284 
00285 
00286 template<class S> 
00287 set<typename S::key_type>
00288 subset(S s, vector<bool> must_be_included)
00289 {
00290     // BEGIN decl.
00291     set<typename S::key_type> ret;
00292     typename S::key_type el;
00293     int i;
00294     typename S::const_iterator i2;
00295     // END
00296 
00297     // BEGIN precond
00298     assert(must_be_included.size() >= s.size());
00299     // END
00300 
00301     for ( i = 0 , i2 = s.begin()  ; i2 != s.end()  ; i++, i2++){
00302         if (must_be_included[i]){
00303             el = *i2;
00304             ret.insert(el);}}
00305     return ret;
00306 }
00307 
00308 vector<bool>
00309 boolean_representation(int integer)
00310 {
00311     // BEGIN decl.
00312     vector<bool> ret;
00313     int num_bits;
00314     int mask, i;
00315     // END
00316 
00317     num_bits = sizeof(integer) * 8;
00318     ret.resize(num_bits);
00319     for (i = 0; i < num_bits; i++){
00320         mask = 1 << i;
00321         ret[i] = ((integer & mask) != 0 ); }
00322     return ret;
00323 }
00324 
00325 
00326 string string_of_boolRepr(vector<bool> v){
00327     // BEGIN decl
00328     string ret;
00329     int i;
00330     // END
00331 
00332     ret = "";
00333     for (i = 0; i < v.size(); i++){
00334         if (v[i]){
00335             ret += "1";}
00336         else{
00337             ret += "0";}}
00338     return ret;}
00339 
00340 
00341 
00342 
00343 float 
00344 scaling_of_char(float char_y,
00345     const room_scaling_data & d)
00346 {
00347     // BEGIN decl
00348     float a, b, tg_alpha;
00349     // END
00350     tg_alpha = (d.scaling_at_y2 - d.scaling_at_y1) / (d.y2 - d.y1);
00351     a = d.scaling_at_y1 - tg_alpha * d.y1;
00352     b = a / tg_alpha;
00353     return (b+ char_y ) * tg_alpha;
00354 }
00355 
00356 
00357 
00358 bool
00359 surf_must_be_printed_before(
00360     const pt<anim_frame_and_pos> c1, 
00361     const pt<anim_frame_and_pos> c2)
00362 {   
00363 
00364 
00365     return (c1->position_y < c2->position_y);
00366 
00367 }
00368 
00369 // pt<result_item_in_inv>
00370 // FACK::item_in_inv_at_position( 
00371 //     int_pair pos) const
00372 // {
00373 //     // BEGIN decl
00374 //     variant<no_item, pt<phys_obj> > ret;
00375 //     int i;
00376 //     int item_rect_left, item_rect_right;
00377 //     int item_rect_top, item_rect_bottom;
00378 //     int item_wt, columns_count;
00379 //     map<int, pt<obj_or_concept> > obj_of_index;
00380 //     int remainder_wt;
00381 //     // END
00382 
00383 
00384 //     obj_of_index[0] = hand;
00385 //     obj_of_index[1] = eye;
00386 //     obj_of_index[2] = mouth;
00387 //     obj_of_index[3] = foot;
00388 //     obj_of_index[4] = body;
00389 //     obj_of_index[5] = ear;
00390 //     obj_of_index[9] = act_pl->;
00391 //     obj_of_index[10] = act_pl->backpack;
00392 
00393 //     item_wt = calc_size_of_inv_items();
00394 //     columns_count = 11; 
00395 
00396 //     item_rect_top = screen->h - item_wt;
00397 //     item_rect_bottom = screen->h -1 ;
00398 
00399 //     for ( i = 0; i< 11; i++)
00400 //     {
00401 
00402 //         item_rect_left =  i * item_wt;
00403 //         item_rect_right = (i+1) * item_wt;
00404 
00405 //         if ( item_rect_left <= pos.x && pos.x < item_rect_right
00406 //             && 
00407 //             item_rect_top <= pos.y && pos.y <= /*sic*/ item_rect_bottom)
00408 //         {
00409 //             if (in(i, obj_of_index))
00410 //             {
00411 //                 return NEW(result_item_in_inv_object_or_conc(map_get(obj_of_index, i)));
00412 //             }
00413 //          else if ( i == 7)
00414 //          {
00415 //              return NEW(result_item_in_inv_special_item_switch_player());
00416 //          }
00417 //          else if ( i == 6)
00418 //          {
00419 //              return NEW(result_item_in_inv_special_item_save_load());
00420 //          }
00421 //          else if ( i == 8)
00422 //          {
00423 //              return NEW(result_item_in_inv_special_item_stay_follow());
00424 //          }
00425 //         }
00426 //     }
00427 
00428 //     // BEGIN check whether the mouse is in the gap to the right of the
00429 //     // screen. This area is associated to the last item.
00430 //     remainder_wt = screen->w % calc_size_of_inv_items();
00431 //     if (remainder_wt >0)
00432 //     {
00433 //         if ( screen->w -remainder_wt <= pos.x && pos.x < screen->w
00434 //             && 
00435 //             item_rect_top <= pos.y && pos.y <= /*sic*/ item_rect_bottom)
00436 //         {
00437 //          return NEW(result_item_in_inv_object_or_conc(map_get(obj_of_index, 10)));
00438 //         }
00439 
00440 //     }
00441 //     // END
00442 
00443 //     return NEW(result_item_in_inv_nothing());
00444 
00445 // }
00446 
00447 // void 
00448 // FACK::render_inventory(
00449 //     int_pair mouse) const
00450 // {
00451 //     // BEGIN decl
00452 //     int columns_count; 
00453 //     int c;
00454 //     int item_wt;
00455 //     SDL_Rect dest_rect;
00456 //     int ret;
00457 //     int remainder_wt;
00458 //     int ht;
00459 //     int item_rect_left, item_rect_right;
00460 //     int item_rect_top, item_rect_bottom;
00461 //     pt<game_state_flashing_inv_t> flashing;
00462 //     pt<PS_governed_by_AI> governed_by_AI;
00463 //     SDL_Surface* surf;
00464 //     map<int, SDL_Surface*> icon_of_index;
00465 //     // END
00466 
00467 //     item_wt = ht = calc_size_of_inv_items();
00468 
00469 
00470         
00471 //     if (!pt_cast(game_state, flashing) && pt_cast(act_pl->state, governed_by_AI))
00472 //     {
00473 //         SDL_Rect dest_rect;
00474 //         dest_rect.x = 0;
00475 //         dest_rect.y = screen->h - ht;
00476 //         dest_rect.w = screen->w;
00477 //         dest_rect.h = ht;
00478 
00479 //         SDL_FillRect(screen, &dest_rect, SDL_MapRGB(screen->format, 10, 0, 0));
00480 
00481 //     }
00482 //     else
00483 //     {
00484       
00485 //         item_rect_top = screen->h - item_wt;
00486 //         item_rect_bottom = screen->h -1 ;
00487 
00488 //         columns_count = 11;
00489 
00490 //         icon_of_index[0] = hand->pick_up_info->get_inv_surf();
00491 //         icon_of_index[1] = eye->pick_up_info->get_inv_surf();
00492 //         icon_of_index[2] = mouth->pick_up_info->get_inv_surf();
00493 //         icon_of_index[3] = foot->pick_up_info->get_inv_surf();
00494 //         icon_of_index[4] = body->pick_up_info->get_inv_surf();
00495 //         icon_of_index[5] = ear->pick_up_info->get_inv_surf();
00496 //         icon_of_index[6] = save_load_icon;
00497 //         icon_of_index[7] = switch_player_icon;
00498 //         icon_of_index[8] = stay_follow_icon;
00499 //         icon_of_index[9] = bulb_icon;
00500 //         icon_of_index[10] = inv_icon;
00501 
00502 
00503 
00504 //         dest_rect.x = 0;
00505 //         dest_rect.y = item_rect_top;
00506 //         dest_rect.w = screen->w;
00507 //         dest_rect.h = item_wt;
00508 //         SDL_FillRect(screen, &dest_rect, SDL_MapRGB(screen->format, 10, 10, 10));
00509 
00510 //         // BEGIN blit inv items
00511 //         for ( c = 0; c< columns_count; c++)
00512 //         {
00513 //             surf = icon_of_index[c];
00514 
00515 //             dest_rect.x = c * item_wt + (item_wt - surf->w)/2;
00516 //             dest_rect.y = item_rect_top +  (item_wt - surf->h)/2;
00517 
00518 //             ret = SDL_BlitSurface(map_get(icon_of_index, c),
00519 //                                   NULL, screen, &dest_rect );
00520 //             assert(ret == 0);
00521 
00522 //             // BEGIN blit mouseover highlight
00523 //             item_rect_left =  c * item_wt;
00524 //             item_rect_right =  (c+1) * item_wt;
00525 
00526 //             if (!pt_cast(game_state, flashing) )
00527 //             {
00528 //                 if ( item_rect_left <= mouse.x && mouse.x < item_rect_right
00529 //                      && 
00530 //                      item_rect_top <= mouse.y && mouse.y <= /*sic*/ item_rect_bottom)
00531 //                 {
00532 //                     rectangleRGBA(screen, 
00533 //                                   item_rect_left, item_rect_top, item_rect_right, item_rect_bottom, 
00534 //                                   200, 100, 100, 200);
00535 //                 }
00536 //             }
00537 //             else
00538 //             {
00539 //                 if ( ( c == 10 && flashing->inv_is_flashing
00540 //                        ||
00541 //                        c == 9 && !flashing->inv_is_flashing)
00542 //                      &&  
00543 //                      int(floor(flashing->timer / 0.3f)) % 2 == 0)
00544 //                 {
00545 //                     rectangleRGBA(screen, 
00546 //                                   item_rect_left, item_rect_top, item_rect_right, item_rect_bottom, 
00547 //                                   200, 100, 100, 200);
00548 
00549 //                 }
00550 //             }
00551 //             // END
00552 //         }
00553 //         // END
00554 
00555 //      // BEGIN check whether the mouse is in the gap to the right of the
00556 //      // screen. This area is associated to the last item.
00557 //      remainder_wt = screen->w % calc_size_of_inv_items();
00558 
00559 //      if ( screen->w -remainder_wt <= mouse.x && mouse.x < screen->w
00560 //           && 
00561 //           item_rect_top <= mouse.y && mouse.y <= /*sic*/ item_rect_bottom)
00562 //      {
00563 //          item_rect_left =  10* item_wt;
00564 //             item_rect_right =  (10+1) * item_wt;
00565 
00566 //          rectangleRGBA(screen, 
00567 //                        item_rect_left, item_rect_top, item_rect_right, item_rect_bottom, 
00568 //                        200, 100, 100, 200);
00569 
00570 //      }
00571 //      // END
00572 
00573 
00574       
00575 //     }
00576 // }
00577 
00578 
00579 bool
00580 hot_zone_square::point_in_zone(
00581     int_pair point) const
00582 {
00583     return (this->x1 <= point.x && point.x <this->x2 && 
00584         this->y1 <= point.y && point.y < this->y2);
00585 }
00586 
00587 bool
00588 hot_zone_pixel_perfect::point_in_zone(
00589     int_pair point) const
00590 {
00591     // BEGIN decl
00592     rgbaf p;
00593     // END
00594 
00595     if ( 0<= point.x && point.x < surf->apparent_wt &&
00596         0<= point.y && point.y < surf->apparent_ht)
00597     {
00598         p = surf->get_pixel( point.x, point.y);
00599         return ( p.a != 0.0f );
00600     }
00601     else
00602     {
00603         return false;
00604     }
00605 }
00606 
00607 bool
00608 player_is_closer_to_the_screen(
00609     const pt<PC> c1, 
00610     const pt<PC> c2)
00611 {   
00612     return (c1->pos.y > c2->pos.y);
00613 }
00614 
00615 
00616 void 
00617 FACK::drop_item(
00618     pt<dragging_state_maybe_dragging_obj> st,
00619     int_pair mouse)
00620 {
00621     // BEGIN decl
00622     list<pt<popup> >::reverse_iterator zo;
00623     int_pair mouse_in_cont_coords, top_left_of_obj_in_cont_coords;
00624     pt<container> cont, co, real_co;
00625     int_pair top_left_of_obj, bottom_right_of_obj;
00626     list<pt<popup> > popups;
00627     int_pair pos;
00628     // END
00629 
00630     popups = act_pl->open_popups;
00631     popups.push_front(act_pl->cache);
00632 
00633     for(zo =  popups.rbegin();
00634         zo != popups.rend();
00635         zo ++)
00636     {
00637         if (pt_cast( *zo, co))
00638         {
00639             mouse_in_cont_coords = mouse - co->position_in_screen;
00640 
00641             top_left_of_obj =  mouse_in_cont_coords - st->offset_of_mouse_in_obj;
00642             bottom_right_of_obj = top_left_of_obj + int_pair(
00643                 st->obj_and_pos.o->get_inv_surf()->w, 
00644                 st->obj_and_pos.o->get_inv_surf()->h);
00645 
00646             if( point_in_rect(top_left_of_obj, co->drop_in_area) &&
00647                 point_in_rect(bottom_right_of_obj, co->drop_in_area ))
00648             {
00649                 if ( co->can_contain_this_obj(st->obj_and_pos.o)
00650                      && 
00651                      (   !pt_cast(st->obj_and_pos.o, cont) 
00652                          ||
00653                          ( cont != co 
00654                            &&
00655                            !contains_recursively(cont, co, real_co /* out*/, pos /* out*/) )))
00656                 {
00657                     if ( st->orig_container == co 
00658                          ||
00659                          st->obj_and_pos.o->can_be_moved_across_containers())
00660                     {
00661                         co->add_item_in_pos(pos_and<pt<obj_or_concept> >(st->obj_and_pos.o, 
00662                                                                             top_left_of_obj));
00663                         return;
00664                     }
00665                     else
00666                     {
00667                         quick_msg = NEW(quick_message("This item cannot be moved across containers."));
00668                         break;
00669                     }
00670                 }
00671                 else
00672                 {
00673                     quick_msg = NEW(quick_message("Item and container incompatible."));
00674                     break; // do not try with containers beneath this one.
00675                 }
00676             }
00677         }
00678     }
00679 
00680     // BEGIN failed. put the item in its original container.
00681     st->orig_container->add_item_in_pos(st->obj_and_pos);
00682     // END
00683 }
00684 
00685 
00686 
00687 pt<container_pick_result>
00688 container::item_at_screen_pos(
00689     int_pair screen_pos,
00690     pt<popup> myself_as_a_smart_ptr) const
00691 {
00692     // BEGIN decl
00693     SDL_Rect rect;
00694     list<pos_and<pt<obj_or_concept> > >::const_reverse_iterator i;
00695     int_pair pos_in_item_coords, pos_in_container_coords;
00696     SDL_Surface* surf;
00697     SDL_Surface* surf2;
00698     Uint32 * addr;
00699     Uint32 raw_pix;
00700     Uint8 r, g, b, a;
00701     // END
00702 
00703 
00704     pos_in_container_coords = screen_pos - this->position_in_screen;
00705 
00706     for( i = this->sorted_items.rbegin(); 
00707          i != this->sorted_items.rend();
00708          i ++)
00709     {
00710         surf = i->o->get_inv_surf();
00711 
00712         pos_in_item_coords = pos_in_container_coords - i->pos;
00713 
00714         if (0 <= pos_in_item_coords.x && pos_in_item_coords.x < surf->w && 
00715             0 <= pos_in_item_coords.y && pos_in_item_coords.y < surf->h)
00716         {
00717             SDL_LockSurface(surf);
00718             addr = (Uint32 *)(surf->pixels) + pos_in_item_coords.y * surf->w + pos_in_item_coords.x;
00719             raw_pix = * addr;
00720             SDL_GetRGBA(raw_pix, surf->format, &r, &g, &b, &a);
00721             SDL_UnlockSurface(surf);
00722             if (a != 0)
00723             {
00724                 return NEW(container_pick_result_obj_and_pos(pos_and<pt<obj_or_concept> >
00725                                                              (i->o, i->pos), 
00726                                                              myself_as_a_smart_ptr));
00727             }
00728         }
00729 
00730     }
00731     // BEGIN check if the container itself was clicked
00732 
00733     if(var_cast(this->closing_area, rect) && point_in_rect(pos_in_container_coords, rect))
00734     {
00735         return NEW(container_pick_result_closing_area(myself_as_a_smart_ptr));
00736     }
00737     else if(this->can_be_dragged)
00738     {
00739         if (point_in_rect(pos_in_container_coords, this->drop_in_area))
00740         {
00741             return NEW(container_pick_result_container_drag_area(myself_as_a_smart_ptr));
00742         }
00743         else
00744         {
00745             surf2 = this->picture;
00746                 
00747             if (0 <= pos_in_container_coords.x && pos_in_container_coords.x < surf2->w && 
00748                 0 <= pos_in_container_coords.y && pos_in_container_coords.y < surf2->h)
00749             {
00750                 SDL_LockSurface(surf2);
00751                 addr = (Uint32 *)(surf2->pixels) + pos_in_container_coords.y * surf2->w + 
00752                     pos_in_container_coords.x;
00753                 raw_pix = * addr;
00754                 SDL_GetRGBA(raw_pix, surf2->format, &r, &g, &b, &a);
00755                 SDL_UnlockSurface(surf2);
00756                 if (a != 0)
00757                 {
00758                     return NEW(container_pick_result_container_drag_area(myself_as_a_smart_ptr));
00759                 }
00760             }
00761         }
00762     }
00763     // END
00764 
00765     return NEW(container_pick_result_void());
00766 }
00767 
00769 pt<container_pick_result>
00770 zoomable::item_at_screen_pos(
00771     int_pair screen_pos,
00772     pt<popup> myself_as_a_smart_ptr ) const
00773 {
00774     // BEGIN decl
00775     SDL_Rect rect;
00776     list<pt<zoomable_zone> >::const_reverse_iterator z;
00777     int_pair  pos_in_container_coords;
00778     SDL_Surface* surf2;
00779     Uint32 * addr;
00780     Uint32 raw_pix;
00781     SDL_Rect surf_rect;
00782     Uint8 r, g, b, a;
00783     // END
00784 
00785     pos_in_container_coords = screen_pos - this->position_in_screen;
00786 
00787     // BEGIN find the alpha value of the pixel
00788     surf2 = this->picture;
00789 
00790     surf_rect = create_rect(0, 0, surf2->w, surf2->h);
00791                 
00792     if (point_in_rect(pos_in_container_coords, surf_rect))
00793     {
00794         SDL_LockSurface(surf2);
00795         addr = (Uint32 *)(surf2->pixels) + pos_in_container_coords.y * surf2->w + 
00796             pos_in_container_coords.x;
00797         raw_pix = * addr;
00798         SDL_GetRGBA(raw_pix, surf2->format, &r, &g, &b, &a);
00799         SDL_UnlockSurface(surf2);
00800     }
00801 
00802     // END
00803 
00804 
00805     for( z = this->sorted_zones.rbegin(); 
00806          z != this->sorted_zones.rend();
00807          z ++)
00808     {
00809 
00810         if (   (*z)->point_in_zone(pos_in_container_coords) 
00811                &&
00812                (  a != 0
00813                   ||
00814                   !(*z)->intersect_rect_and_picture))
00815         {
00816             return NEW(container_pick_result_obj(
00817                            (*z)->obj, 
00818                            myself_as_a_smart_ptr));
00819         }
00820 
00821     }
00822     // BEGIN check if the container itself was clicked
00823 
00824     if(var_cast(this->closing_area, rect) && point_in_rect(pos_in_container_coords, rect))
00825     {
00826         return NEW(container_pick_result_closing_area(myself_as_a_smart_ptr));
00827     }
00828     else
00829     {
00830         if (point_in_rect(pos_in_container_coords, surf_rect) // then a was calculated earlier...
00831             &&
00832             a != 0)
00833         {
00834             return NEW(container_pick_result_container_drag_area(myself_as_a_smart_ptr));
00835         }
00836 
00837     }
00838     // END
00839     return NEW(container_pick_result_void());
00840 }
00841 
00842 
00843 pt<container_pick_result>
00844 FACK::item_in_popup_at_screen_pos(
00845     int_pair screen_pos)  const
00846 {
00847     // BEGIN decl
00848     list<pt<popup> >::reverse_iterator po;
00849     list<pt<popup> > popups;
00850     pt<container> co;
00851     pt<zoomable> zo;
00852     pt<container_pick_result> pick_res;
00853     pt<container_pick_result_void> void_res;
00854     // END
00855 
00856     popups = act_pl->open_popups;
00857     popups.push_front(act_pl->cache);
00858 
00859     for(po =  popups.rbegin();
00860         po != popups.rend();
00861         po++)
00862     {
00863         pick_res = (*po)->item_at_screen_pos(screen_pos, *po);
00864        
00865         if(!pt_cast(pick_res, void_res))
00866         {
00867             return pick_res;
00868         }
00869     }
00870     return NEW(container_pick_result_void());
00871 
00872 }
00873 
00874 
00875 variant<no_item, pt<obj_or_concept> >
00876 item_in_room_at_position(
00877     int_pair pos,
00878     list<pt<PC> > players,
00879     const pt<PC> act_pl,
00880     const map<pt<PC>, pt<anim_frame> > & cur_frame_of_player)
00881 {
00882     // BEGIN decl
00883     list<pt<bg_hot_zone> >::const_iterator z;
00884     list<pt<PC> >::const_iterator pl;
00885     pt<PC> item2;
00886     pt<bg_hot_zone> item1;
00887     pt<still_situation_sitting> sitting;
00888     bool must_be_scaled;
00889     float scal;
00890     // END
00891 
00892     foreach(z, act_pl->loc->sorted_hot_zones){
00893         if( (*z)->visible && (*z)->point_in_zone(pos))
00894         {
00895             item1 = *z;
00896             break;
00897         }
00898     }
00899 
00900     players.sort(player_is_closer_to_the_screen);
00901 
00902     foreach(pl, players){
00903         
00904         must_be_scaled = !pt_cast((*pl)->still_situat, sitting);
00905 
00906         scal = (must_be_scaled? 
00907                 scaling_of_char( (*pl)->pos.y, act_pl->loc->scaling_data):
00908                 1.0f);
00909 
00910         if( (*pl) != act_pl
00911             &&
00912             (*pl)->loc == act_pl->loc 
00913             && 
00914             map_get(
00915                 cur_frame_of_player, 
00916                 (*pl))  ->  point_in_surf( pos,
00917                                            (*pl)->pos,
00918                                            scal))
00919         {
00920             item2 = *pl;
00921             break;
00922         }
00923     }
00924 
00925     if (item1 && !item2)
00926     {
00927         return item1->obj;
00928     }
00929     else if (item2 && !item1)
00930     {
00931         return item2->obj;
00932     }
00933     else if (item1 && item2)
00934     {
00935         if (item1->y_walkbehind > item2->pos.y)
00936         {
00937             //cout << "choosing zone: zone y  = " << item1->y_walkbehind << ", PC y = " << item2->pos.y <<  endl;
00938             return item1->obj;
00939         }
00940         else
00941         {
00942             //cout << "choosing PC" << endl;
00943             return item2->obj;
00944         }
00945     }
00946     else
00947     {
00948         return no_item();
00949     }
00950 }
00951 
00952 
00953 bool
00954 printable_must_be_printed_before(
00955     const pt<printable> p1, 
00956     const pt<printable> p2 )
00957 {
00958     return p1->y() < p2->y();
00959 }
00960 
00961 
00962 void
00963 render_layers_and_chars_in_correct_order(
00964     list< pt<printable> >& layers_and_chars_except_bg,
00965     cfsurf & bg_surf,
00966     SDL_Surface * screen,
00967     const room_scaling_data& d,
00968     SDL_Rect visible_rect_in_src_surf,
00969     set<pt<light> > active_lights)
00970 {
00971     // BEGIN decl.
00972     list<pt<printable> >::const_iterator l;
00973     // END
00974 
00975     layers_and_chars_except_bg.sort(printable_must_be_printed_before);
00976 
00977     foreach(l, layers_and_chars_except_bg){
00978         (*l)->print_with_transparency(bg_surf, d, active_lights);
00979     }
00980     bg_surf.opaque_blit_to_sdl_surface( screen, visible_rect_in_src_surf);
00981 
00982 }
00983         
00984         
00985 
00986 Uint32 choose_some_video_flags(){
00987     // BEGIN decl
00988     const SDL_VideoInfo *videoInfo;
00989     Uint32 videoflags;
00990     // END
00991 
00992           
00993     videoflags = SDL_DOUBLEBUF;
00994     videoInfo = SDL_GetVideoInfo( );
00995 
00996     if ( !videoInfo ){
00997         raise_exception( "Video query failed: " + string(SDL_GetError()));
00998     }
00999     else{
01000         if ( videoInfo->hw_available ){
01001             videoflags |= SDL_HWSURFACE;
01002             cout << "HW Surface available" << endl;
01003         }
01004         else{
01005             videoflags |= SDL_SWSURFACE;
01006             cout << "SW Surface available" << endl;
01007         }
01008         if ( videoInfo->blit_hw ){
01009             videoflags |= SDL_HWACCEL;
01010             cout << "HW ACCEL available" << endl;
01011         }
01012                         
01013     }
01014         
01015     return videoflags;
01016 }
01017 
01018 
01019 
01020 pt<vector2<bool> > 
01021 walking_map_from_sdl_surface(SDL_Surface * s)
01022 {
01023     // BEGIN decl.
01024     pt<vector2<bool> > m;
01025     int x, y;
01026     rgbaf pix;
01027     Uint32 raw_pixel;
01028     Uint32 * ptr;
01029     Uint8 r, g,b, a;
01030     // END
01031 
01032 
01033     m = NEW( vector2<bool>(s->w, s->h));
01034     SDL_LockSurface(s);
01035     for (x = 0; x< s->w; x++){
01036         for (y = 0; y< s->h; y++){
01037             ptr = (Uint32 *) (s->pixels) + x + y * s->w;
01038             raw_pixel = * ptr;
01039             SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
01040             m->set( x , y, a != 0);
01041         }
01042     }
01043     SDL_UnlockSurface(s);
01044     return m;}
01045 
01046 
01047 bool
01048 is_walkable
01049 ( const vector2<bool>& walking_map, int x, int y)
01050 {
01051     if ( 0 <= x && x < walking_map.w
01052         &&
01053         0 <= y && y < walking_map.h)
01054     {
01055         return walking_map.get( x , y);
01056     }
01057     else
01058     {
01059         return false;
01060     }
01061 
01062 }
01063 
01064 namespace path_finding{
01065 
01066 
01067     bool int_pair::operator==(const int_pair& p) const{
01068         return ( x == p.x && y == p.y);
01069     }
01070     bool int_pair::operator<(const int_pair& p) const{
01071         if(x < p.x)
01072             return true;
01073         else if (x > p.x){
01074             return false;}
01075         else{
01076             if ( y < p.y){
01077                 return true;}
01078             else if (y > p.y){
01079                 return false;}
01080             else{
01081                 return false;}}}
01082 
01083     struct frontier_node{
01084             int_pair position;
01085             int cost_g;
01086             float cost_h;
01087 
01088             frontier_node(int_pair position, int cost_g, float cost_h){
01089                 this->position = position;
01090                 this->cost_h = cost_h;
01091                 this->cost_g = cost_g;}
01092             frontier_node(){}
01093     };
01094 
01095 
01096     struct int_pair_and_cost{
01097             int_pair pair;
01098             int cost;
01099             int_pair_and_cost(int_pair pair, int cost){
01100                 this->pair = pair;
01101                 this->cost = cost;}
01102     };
01103 
01104     list<int_pair_and_cost>
01105     neighbours(  int_pair node)
01106     {
01107         // BEGIN decl
01108         list<int_pair_and_cost> ret;
01109         // END
01110 
01111         ret.push_back(int_pair_and_cost(int_pair(node.x-1, node.y), 10));
01112         ret.push_back(int_pair_and_cost(int_pair(node.x+1, node.y), 10));
01113         ret.push_back(int_pair_and_cost(int_pair(node.x, node.y-1), 10));
01114         ret.push_back(int_pair_and_cost(int_pair(node.x, node.y+1), 10));
01115         ret.push_back(int_pair_and_cost(int_pair(node.x-1, node.y-1), 11));
01116         ret.push_back(int_pair_and_cost(int_pair(node.x+1, node.y+1), 11));
01117         ret.push_back(int_pair_and_cost(int_pair(node.x+1, node.y-1), 11));
01118         ret.push_back(int_pair_and_cost(int_pair(node.x-1, node.y+1), 11));
01119         return ret;
01120     }
01121 
01122     float
01123     distance( int_pair p1, int_pair p2){
01124         // BEGIN decl
01125         float x, y;
01126         // END
01127 
01128         x = float(p1.x - p2.x);
01129         y = float(p1.y - p2.y);
01130         return sqrt( x * x + y * y);
01131     }
01132 
01133 
01134     bool
01135     compare_frontier_nodes(const frontier_node& f1,
01136         const frontier_node& f2){
01137         return f1.cost_g + f1.cost_h < f2.cost_g + f2.cost_h;     
01138 
01139     }
01140 
01141     bool 
01142     int_pair__equal(int_pair p1, int_pair p2){
01143         return p1.x == p2.x && p1.y == p2.y;}
01144 
01145     string
01146     string_of_int_pair(int_pair p){
01147         string ret;
01148         ret = string_of_int(p.x);
01149         ret += ", " + string_of_int(p.y);
01150         return ret;
01151     }
01152 
01153     struct no_route_found{};
01154 
01157     variant<no_route_found, pt<list<int_pair> > >
01158     best_route(
01159         int_pair from,
01160         int_pair to,
01161         const vector2<bool>& walkable)
01162     {
01163         // BEGIN decl.
01164         pt<list<int_pair> > route;
01165         list<int_pair>::const_iterator it;
01166 
01167         vector<int_pair> route2;
01168         list<frontier_node> frontier, nei3;
01169         frontier_node chosen_node;
01170         vector2<bool> visited;
01171         list<int_pair_and_cost> nei;
01172         list<int_pair_and_cost> nei2;
01173         list<int_pair_and_cost>::const_iterator n;
01174         int_pair nn;
01175         map<int_pair, int_pair> parent_of;
01176         map<int_pair, int_pair>::const_iterator parent_it;
01177         // END
01178 
01179         // BEGIN precond
01180         assert( walkable.get(from.x, from.y));
01181         assert( walkable.get(to.x, to.y));
01182         // END
01183 
01184         if (from == to)
01185         {
01186             return pt<list<int_pair> >();
01187         }
01188         else
01189         {
01190 
01191             visited = vector2<bool>(walkable.w, walkable.h);
01192             visited.fill_with(false);
01193             frontier.push_back(frontier_node(
01194                                    from, 0, 
01195                                    100 /* cost_h is irrelevant*/));
01196             visited.set(from.x, from.y, true);
01197             
01198             while(true)
01199             {
01200                 if (frontier.empty())
01201                 {
01202                     return no_route_found();
01203                 }
01204                 else
01205                 {
01206                     chosen_node = frontier.front();  
01207                     frontier.pop_front();
01208 
01209                     if (int_pair__equal(chosen_node.position, to))
01210                     {
01211                         nn = to;
01212                         route = NEW( list<int_pair>());
01213                         route->push_front(nn);
01214                         while(! int_pair__equal( nn,from))
01215                         {
01216                             parent_it = parent_of.find(nn);
01217                             assert(parent_it  != parent_of.end());
01218                             nn = parent_it->second;
01219                             route->push_front(nn);
01220                         }
01221                         assert(route->front() == from);
01222                         route->pop_front();
01223                         return route;
01224                     }
01225                     else
01226                     {
01227                         nei = neighbours(chosen_node.position);
01228                         
01229                         setof( n,
01230                                nei,
01231                                ( n->pair.x >= 0 && n->pair.x <walkable.w
01232                                  &&
01233                                  n->pair.y >= 0 && n->pair.y <walkable.h
01234                                  &&
01235                                  ! visited.get( n->pair.x, n->pair.y) 
01236                                  &&
01237                                  walkable.get( n->pair.x, n->pair.y) ),
01238                                nei2);
01239 
01240                         foreach(n, nei2){
01241                             assert(!visited.get( n->pair.x, n->pair.y));
01242                             visited.set(n->pair.x, n->pair.y, true);       
01243                             parent_of[n->pair] = chosen_node.position;
01244                         }
01245 
01246                         setof_( frontier_node(n->pair /* pos */,
01247                                     chosen_node.cost_g + n->cost /* cost_g */,
01248                                     distance(n->pair, to) /* cost_h */),
01249                             n,
01250                             nei2,
01251                             true,
01252                             nei3);
01253 
01254                         nei3.sort(compare_frontier_nodes);
01255                         frontier.merge(nei3, compare_frontier_nodes);
01256                     }
01257                 }
01258             }
01259             assert(false);
01260         }
01261     }
01262 }; // namespace path_finding
01263 
01264 
01265 
01266 using path_finding::best_route;
01267 using path_finding::no_route_found;
01268 
01269 
01270 
01271 
01272 bool
01273 walk_frame_id::operator< (
01274     const walk_frame_id& w)const
01275 {
01276     if (dir < w.dir)
01277     {
01278         return true;
01279     }
01280     else if (dir > w.dir)
01281     {
01282         return false;
01283     }
01284     else
01285     {
01286         if (foot < w.foot)
01287         {
01288             return true;
01289         }
01290         else if (foot > w.foot)
01291         {
01292             return false;
01293         }
01294         else
01295         {
01296             if (phase < w.phase)
01297             {
01298                 return true;
01299             }
01300             else// if (phase > w.phase)
01301             {
01302                 return false;
01303             }
01304         }
01305     }
01306 }
01307 
01308 
01309 
01310 
01311 pt<list<int_pair> >
01312 compute_feet_positions(
01313     int_pair start_position,
01314     const list<int_pair>& route,
01315     const room_scaling_data& scaling_data,
01316     float walk_step_horiz,
01317     float walk_step_vert)
01318 {
01319     // BEGIN decl.
01320     pt<list<int_pair> > route2;
01321     int_pair new_candidate, latest_certain_foot_pos;
01322     list<int_pair>::const_iterator route_it;
01323     float scal_of_cur_step, delta_x, delta_y;
01324     // END
01325     
01326     // BEGIN precond
01327     assert(route.size()>0);
01328     assert(! (route.front() == start_position));
01329     // END
01330 
01331     route2 = NEW( list<int_pair>());
01332 
01333     latest_certain_foot_pos = start_position;
01334     route_it = route.begin();
01335 
01336     scal_of_cur_step = scaling_of_char(float(latest_certain_foot_pos.y), scaling_data);
01337 
01338     do
01339     {
01340         new_candidate = *route_it;
01341 
01342 
01343         delta_x = float(std::abs(new_candidate.x - latest_certain_foot_pos.x));
01344         delta_y = float(std::abs(new_candidate.y - latest_certain_foot_pos.y));
01345 
01346         if(delta_x > scal_of_cur_step * walk_step_horiz || 
01347             delta_y > scal_of_cur_step * walk_step_vert)
01348         {
01349             latest_certain_foot_pos = new_candidate;
01350             route2->push_back(latest_certain_foot_pos);
01351             scal_of_cur_step = scaling_of_char(float(latest_certain_foot_pos.y), scaling_data);
01352         }
01353 
01354         route_it ++;
01355         if(route_it == route.end())
01356         {
01357             break;
01358         }
01359 
01360     }while(true);
01361 
01362     if(!(latest_certain_foot_pos == route.back()))
01363     {
01364         route2->push_back(route.back());
01365     }
01366     return route2;
01367 }
01368 
01369 
01370 
01371 
01372 
01373 direction
01374 compute_dir(int_pair p1, int_pair p2, float walk_step_horiz)
01375 {
01376 
01377 
01378     if(p2.x - p1.x >= walk_step_horiz * 0.8f  ){
01379         return d_right;}
01380     else if (p1.x - p2.x >= walk_step_horiz * 0.8f){
01381         return d_left;}
01382     else{
01383         if(p2.y < p1.y){
01384             return d_up;}
01385         else if (p2.y > p1.y){
01386             return d_down;}
01387         else{
01388             if(p2.x < p1.x){
01389                 return d_left;}
01390             else if (p2.x > p1.x){
01391                 return d_right;}
01392 
01393         }
01394 
01395 
01396     }
01397 
01398 }
01399 
01400 
01401     
01402 struct walking_finished{};
01403 
01404 variant<walking_finished, pair<int_pair, direction> >
01405 update_walking_animation(
01406     float frame_change_interval,
01407     pt<AI_substate_walk>  state_walk,
01408     int_pair player_pos,
01409     float walk_step_horiz,
01410     float dt,
01411     direction cur_dir)
01412 {
01413     // BEGIN decl
01414     int_pair new_pos;
01415     // END
01416 
01417     state_walk->timer += dt;
01418 
01419     if (state_walk->timer <= frame_change_interval)
01420     {
01421         return make_pair(player_pos, cur_dir);
01422     }
01423     else{
01424         state_walk->timer -= frame_change_interval;
01425 
01426 //              if(state_walk->cur_phase == HIGH_POINT){
01427 //                  state_walk->cur_phase = CONTACT;}
01428 //              else
01429 
01430         if (state_walk->cur_phase == RECOIL)
01431         {
01432             state_walk->cur_phase = PASSING;
01433             return make_pair(player_pos, cur_dir);
01434         }
01435         else if (state_walk->cur_phase == PASSING)
01436         {
01437             //state_walk->cur_phase = HIGH_POINT;}
01438             state_walk->cur_phase = CONTACT;
01439             return make_pair(player_pos, cur_dir);
01440         }
01441         else if (state_walk->cur_phase == CONTACT){
01442 
01443             state_walk->cur_phase = RECOIL;
01444 
01445             // BEGIN only in the RECOIL frame, we change foot
01446             // and update the position
01447             if(state_walk->cur_foot == hd_right){
01448                 state_walk->cur_foot = hd_left;}
01449             else{
01450                 state_walk->cur_foot = hd_right;}
01451                     
01452 
01453             if (state_walk->cur_pos >= state_walk->route.size()){
01454                 return walking_finished();
01455             }
01456             else{
01457                 new_pos = state_walk->route[state_walk->cur_pos];
01458                 
01459                 state_walk->cur_pos ++;
01460 
01461                 return make_pair(new_pos,
01462                     compute_dir(player_pos, new_pos, walk_step_horiz));
01463             }
01464             // END
01465         }
01466 
01467     }
01468 
01469 
01470 }
01471 
01472 list<SDL_Event> 
01473 get_sdl_events()
01474 {
01475     // BEGIN decl
01476     list<SDL_Event> ret;
01477     SDL_Event ev;
01478     // END
01479 
01480     while(SDL_PollEvent(&ev)){
01481         ret.push_back(ev);}
01482 
01483     return ret;
01484 
01485 }
01486 
01487 
01488 
01489 
01490 
01491 
01492 
01493 namespace text{
01494 
01495     bool
01496     is_alnum(char c)
01497     {
01498         return ( 65 <= c && c <=90 
01499             ||
01500             97 <= c && c <= 122);
01501     }
01502 
01503     list<string>
01504     tokenize(string t)
01505     {
01506         // BEGIN decl
01507         list<string> ret;
01508         int i; 
01509         char c;
01510         string cur_word;
01511         bool previous_was_alnum;
01512         // END
01513 
01514         cur_word = "";
01515         previous_was_alnum = true;
01516         for (i = 0; i < t.size(); i++){
01517             c = t[i];
01518             if (is_alnum(c)){
01519                 if (previous_was_alnum){
01520                     cur_word += c;}
01521                 else{
01522                     ret.push_back(cur_word);
01523                     cur_word = "";
01524                     cur_word += c;
01525                     previous_was_alnum = true;}}
01526             else{
01527                 cur_word += c;
01528                 ret.push_back(cur_word);
01529                 cur_word = "";
01530                 previous_was_alnum = false;
01531             }
01532         }
01533         if (cur_word != ""){
01534             ret.push_back(cur_word);}
01535         return ret;
01536     }
01537 
01538     int 
01539     text_wt_in_pixels(string s, 
01540         const surf_of_letter_t & surf_of_letter)
01541     {
01542         // BEGIN decl
01543         int wt; int i;
01544         // END
01545 
01546         wt = 0;
01547         for (i = 0; i<s.size(); i++){
01548             wt += map_get(surf_of_letter, s[i])->w;
01549         }
01550         return wt;
01551     }
01552 
01553     void
01554     print_letter(
01555         SDL_Surface * l, 
01556         SDL_Surface * screen,
01557         int_pair dest_pos,
01558         rgb col)
01559     {
01560         // BEGIN decl
01561         int x, y;
01562         Uint32* dest_addr, *src_addr;
01563         Uint32 raw_pix;
01564         Uint8 r, g, b, a;
01565         // END  
01566 
01567         // BEGIN precond
01568         assert(screen->format->BytesPerPixel == 4);
01569         assert(l->format->BytesPerPixel == 4);
01570         // END
01571 
01572         SDL_LockSurface(screen);
01573         SDL_LockSurface(l);
01574         for (x = 0; x < l->w ; x++)
01575         {
01576             for (y = 0; y < l->h ; y++)
01577             {
01578                 src_addr = (Uint32 *) (l->pixels) + x + y * l->w;
01579                 raw_pix = *src_addr;
01580 
01581                 SDL_GetRGBA(raw_pix, l->format, &r, &g, &b, &a);
01582 
01583                 dest_addr = (Uint32 *) (screen->pixels) + (dest_pos.x + x) + (dest_pos.y + y) * screen->w;
01584                 if(a == 0)
01585                 {
01586                 }
01587                 else if (r==0)
01588                 {
01589                     * dest_addr = SDL_MapRGB(screen->format , r, g, b);
01590                 }
01591                 else// if (r==255)
01592                 {
01593                     * dest_addr = SDL_MapRGB(screen->format , col.r, col.g, col.b);
01594                 }
01595             }
01596         }
01597         SDL_UnlockSurface(screen);
01598         SDL_UnlockSurface(l);
01599     }
01600 
01602     int
01603     print_line_of_text(string t, int x, int y,
01604         const surf_of_letter_t & surf_of_letter,
01605         SDL_Surface * screen,
01606         bool calc_wt_only,
01607         rgb col)
01608     {
01609         // BEGIN decl
01610         int i, cur_x;
01611         SDL_Rect dest_rect;
01612         char c;
01613         // END
01614 
01615         cur_x = x;
01616 
01617         for (i = 0; i< t.size(); i++)
01618         {
01619             dest_rect.y = y;
01620             dest_rect.x = cur_x;
01621 
01622             c = t[i];
01623 
01624             if (!calc_wt_only)
01625             {
01626 //              SDL_BlitSurface( map_get(surf_of_letter, c),
01627 //                  NULL,
01628 //                  screen,
01629 //                  &dest_rect);
01630                 print_letter( 
01631                     map_get(surf_of_letter, c),
01632                     screen, 
01633                     int_pair(cur_x, y),
01634                     col);
01635             }
01636 
01637             cur_x += map_get(surf_of_letter, c)->w;
01638         }
01639         return cur_x - x;
01640     }
01641 
01642     void
01643     print_x_centered_line_of_text(string t, int x_min, int x_max, int y,
01644         const surf_of_letter_t & surf_of_letter,
01645         SDL_Surface * screen, rgb col)
01646     {
01647         // BEGIN decl
01648         int avail_wt, wt, final_x;
01649         // END
01650         avail_wt = x_max - x_min;
01651         wt = print_line_of_text(t, x_min, y, surf_of_letter, screen, true, col);
01652         assert(wt < avail_wt);
01653 
01654         final_x = x_min + (avail_wt - wt)/2;
01655         print_line_of_text(t, final_x, y, surf_of_letter, screen, false, col);
01656 
01657     }
01658 
01659     int
01660     draw_text_multiline_variable_ht(string text,
01661         SDL_Surface* surf,
01662         int x_left,
01663         int y_top,
01664         int x_right,
01665         const surf_of_letter_t  & surf_of_letter,
01666         bool calc_ht_only, 
01667         rgb col)
01668     {
01669         // BEGIN decl
01670         int cur_line_wt; 
01671         list<string>::const_iterator t;
01672         int w; 
01673         int avail_wt;
01674         list<string> tokens;
01675         string cur_line;
01676         int ht;
01677         char random_letter;
01678         // END
01679 
01680         tokens = tokenize(text);
01681         avail_wt = x_right - x_left;
01682         assert(avail_wt > 0);
01683         random_letter = text[0];
01684         cur_line_wt = 0;
01685         cur_line = "";
01686         ht = 0;
01687         foreach( t, tokens){
01688             w = text_wt_in_pixels(*t, surf_of_letter);
01689             assert(w < avail_wt );
01690             if (cur_line_wt + w < avail_wt){
01691                 cur_line_wt +=w;
01692                 cur_line += *t;
01693             }
01694             else{
01695                 // BEGIN print cur_line and increment ht
01696                 if (!calc_ht_only)
01697                 {
01698                     print_x_centered_line_of_text(cur_line, x_left, x_right, y_top + ht, surf_of_letter, surf, col);
01699                 }
01700                 ht += map_get(surf_of_letter, random_letter)->h;
01701                 // END
01702 
01703                 cur_line = "";
01704                 cur_line += *t;
01705                 cur_line_wt = w;
01706             }
01707         }
01708 
01709         if (cur_line != ""){    
01710             // BEGIN print cur_line and increment ht
01711             if (!calc_ht_only){
01712                 print_x_centered_line_of_text(cur_line, x_left, x_right, y_top + ht, surf_of_letter, surf, col);}
01713             ht += map_get(surf_of_letter, random_letter)->h;
01714             // END
01715 
01716         }
01717         return ht;
01718     }
01719 };
01720 
01721 using text::draw_text_multiline_variable_ht;
01722 using text::print_line_of_text;
01723 using text::print_x_centered_line_of_text;
01724 
01725 
01726 
01727 // bool
01728 // item_is_ambiguous(
01729 //     const pt<obj_or_concept> i)
01730 // {
01731 //     pt<phys_obj_with_verbs> phys;
01732 
01733 //     if(pt_cast(i, phys))
01734 //     {
01735 //         return ( phys->verbs.size() != 0);
01736 //     }
01737 //     else
01738 //         return false;
01739 // }
01740 
01741 
01742 
01743 void
01744 FACK::render_command_bar( 
01745     int_pair mouse_screen,
01746     int_pair mouse_bg,
01747     const map<pt<PC>, pt<anim_frame> > & cur_frame_of_player) const
01748 {
01749     // BEGIN decl
01750     SDL_Rect dest_rect;
01751     pt<PS_missing_one_item> missing_one;
01752     pt<PS_missing_two_items> missing_two;
01753     variant<no_item, pt<obj_or_concept> > ret2;
01754     pt<obj_or_concept> item;
01755     string selected_item_text;
01756     rgb text_color_of_command_bar(120, 140, 200);
01757     Uint32 bg_color_of_command_bar;
01758     pt<game_state_flashing_inv_t> flashing;
01759     pt<container_pick_result> pick_res;
01760     pt<container_pick_result_obj_and_pos> obj_and_pos;
01761     pt<container_pick_result_obj> obj;
01762     pt<container_pick_result_container_drag_area> container_drag_area;
01763     pt<container_pick_result_closing_area> closing_area;
01764     special_button_pick_result special_but;
01765     // END
01766 
01767     bg_color_of_command_bar = SDL_MapRGB(screen->format, 10,10,15);
01768 
01769 
01770     dest_rect.x = 0;
01771     dest_rect.y = screen->h - act_pl->cache->picture->h - calc_command_bar_ht();
01772     dest_rect.w = screen->w;
01773     dest_rect.h = calc_command_bar_ht();
01774     SDL_FillRect(screen, &dest_rect, bg_color_of_command_bar);
01775 
01776     if(!pt_cast(game_state, flashing))
01777     {
01778 
01779         special_but = special_button_at_pos(mouse_screen);
01780         if(special_but == SBPR_STAY_FOLLOW)
01781         {
01782             selected_item_text = "stay/follow";
01783 
01784             print_x_centered_line_of_text( 
01785                 selected_item_text,
01786                 0, screen->w,
01787                 screen->h -  calc_command_bar_ht() -  act_pl->cache->picture->h +1,
01788                 surf_of_letter,
01789                 screen,
01790                 text_color_of_command_bar);
01791         }
01792         else if (special_but == SBPR_CYCLE_PLAYER)
01793         {
01794             selected_item_text = "switch active player";
01795 
01796             print_x_centered_line_of_text( 
01797                 selected_item_text,
01798                 0, screen->w,
01799                 screen->h -  calc_command_bar_ht() -  act_pl->cache->picture->h +1,
01800                 surf_of_letter,
01801                 screen,
01802                 text_color_of_command_bar);
01803 
01804         }
01805         else if (special_but == SBPR_SAVE_LOAD)
01806         {
01807             selected_item_text = "Options";
01808 
01809             print_x_centered_line_of_text( 
01810                 selected_item_text,
01811                 0, screen->w,
01812                 screen->h -  calc_command_bar_ht() -  act_pl->cache->picture->h +1,
01813                 surf_of_letter,
01814                 screen,
01815                 text_color_of_command_bar);
01816 
01817         }
01818         else
01819         {
01820             pick_res = item_in_popup_at_screen_pos(mouse_screen);
01821 
01822             ret2 = item_in_room_at_position(
01823                 mouse_bg,
01824                 players, act_pl, cur_frame_of_player);
01825 
01826             if( pt_cast(act_pl->state, missing_one))
01827             {
01828                 if( pt_cast(pick_res, obj_and_pos) &&
01829                     obj_and_pos->obj_and_pos.o != missing_one->obj_already_chosen)
01830                 {
01831                     selected_item_text = obj_and_pos->obj_and_pos.o->readable_name;
01832                 }
01833                 else if( pt_cast(pick_res, obj) &&
01834                     obj->obj != missing_one->obj_already_chosen)
01835                 {
01836                     selected_item_text = obj->obj->readable_name;
01837                 }
01838                 else if(pt_cast(pick_res, container_drag_area) ||
01839                         pt_cast(pick_res, closing_area))
01840                 {
01841                     selected_item_text = "";
01842                 }
01843                 else if ( var_cast(ret2, item) 
01844                           && 
01845                           item != missing_one->obj_already_chosen)
01846                 {
01847                     selected_item_text = item->readable_name;
01848                 }
01849                 else{
01850                     selected_item_text = "...";
01851                 }
01852 
01853                 print_x_centered_line_of_text( 
01854                     missing_one->obj_already_chosen->readable_name + " + " + selected_item_text,
01855                     0, screen->w,
01856                     screen->h - calc_command_bar_ht() - act_pl->cache->picture->h +1,
01857                     surf_of_letter,
01858                     screen,
01859                     text_color_of_command_bar);
01860             }
01861             else if (pt_cast(act_pl->state, missing_two))
01862             {
01863                 if(pt_cast(pick_res, obj_and_pos))
01864                 {
01865                     selected_item_text = obj_and_pos->obj_and_pos.o->readable_name;
01866                 }
01867                 else if(pt_cast(pick_res, obj))
01868                 {
01869                     selected_item_text = obj->obj->readable_name;
01870                 }
01871                 else if(pt_cast(pick_res, container_drag_area) ||
01872                         pt_cast(pick_res, closing_area))
01873                 {
01874                     selected_item_text = "";
01875                 }
01876                 else if ( var_cast(ret2, item) )
01877                 {
01878                     selected_item_text = item->readable_name;
01879                 }
01880                 else
01881                 {
01882                     selected_item_text = "";
01883                 }
01884                 print_x_centered_line_of_text( 
01885                     selected_item_text,
01886                     0, screen->w,
01887                     screen->h -  calc_command_bar_ht() - act_pl->cache->picture->h +1,
01888                     surf_of_letter,
01889                     screen,
01890                     text_color_of_command_bar);
01891             }
01892         }
01893     }
01894 }
01895 
01896 
01897 void
01898 draw_verb_dialog(
01899     pt<phys_obj> item1,
01900     pt<phys_obj> item2,
01901     const surf_of_letter_t & surf_of_letter,
01902     SDL_Surface * screen,
01903     bool calc_rect_only,
01904     int_pair mouse,
01906     SDL_Rect & cancel_rect,
01908     list<pt<dialog_choice> > & choices)
01909 {
01910     // BEGIN decl
01911     int ht_label, avail_ht;
01912     int y_top, y_bottom;
01913     int ht_per_verb, ht;
01914     int left_border, right_border;
01915     SDL_Rect rect;
01916     string  text;
01917     int ht_of_letter, centered_y;
01918     vector<pt<verb> >::const_iterator v;
01919     pt<verb> cur_verb;
01920 //     rgb text_color_of_working_verb(200,200,200);
01921 //     rgb text_color_of_not_working_verb(120,120,120);
01922     rgb color_of_less_important_text(80,120,120);
01923     rgb color_of_none_of_the_above(250,250,150);
01924     rgb col;
01925     list<pt<token_of_verb_text> >::const_iterator tok;
01926     pt<phys_obj_with_verbs> obj_with_verbs;
01927     vector<pt<phys_obj> > items;
01928     vector<pt<phys_obj> >::const_iterator i;
01929     pt<phys_obj> active_it, passive_it;
01930     int c;
01931     int num_choices;
01932     // END
01933 
01934     // BEGIN clear screen
01935     if (! calc_rect_only)
01936         SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 10, 10, 10));
01937     // END
01938 
01939 
01940     // BEGIN draw label
01941     ht_of_letter = map_get(surf_of_letter, 'a')->h;
01942 
01943     left_border = 10;
01944     right_border = screen->w - 10;
01945 
01946     ht_label = draw_text_multiline_variable_ht( ( "Please specify what you want to do."),
01947                                                 screen,
01948                                                 left_border,
01949                                                 0,
01950                                                 right_border,
01951                                                 surf_of_letter,
01952                                                 calc_rect_only,
01953                                                 color_of_less_important_text);
01954     // END
01955 
01956 
01957 
01958     avail_ht = screen->h - ht_label;
01959 
01960     items = *vector_of(ulist(item1) << item2);
01961 
01962 
01963 
01964     // BEGIN calc ht_per_verb
01965     num_choices = 1 /* cancel button */ ;
01966 
01967     foreach(i, items){
01968 
01969         if(pt_cast(*i, obj_with_verbs))
01970         {
01971             num_choices += obj_with_verbs->verbs.size();
01972         }
01973 
01974     }
01975     if ( (pt_cast(item1, obj_with_verbs) && obj_with_verbs->none_of_the_above)
01976          ||
01977          (pt_cast(item2, obj_with_verbs) && obj_with_verbs->none_of_the_above))
01978     {
01979         num_choices ++ ;
01980     }
01981 
01982     ht_per_verb = avail_ht / num_choices;
01983     // END
01984 
01985 
01986 
01987     
01988     choices.clear();
01989 
01990     for(c = 0; c < 2; c++)
01991     {
01992         active_it = items[c];
01993         passive_it = items[1-c];
01994 
01995 
01996         if(pt_cast(active_it, obj_with_verbs))
01997         {
01998             foreach(v, obj_with_verbs->verbs)
01999             {
02000                 y_top = ht_label + choices.size() * ht_per_verb;
02001                 y_bottom = ht_label + (choices.size() +1)* ht_per_verb;
02002 
02003                 centered_y = y_top + (ht_per_verb - ht_of_letter)/2;
02004 
02005                 cur_verb = *v;
02006 
02007                 text = "";
02008                 foreach(tok, cur_verb->tokens){
02009                     text += (*tok)->to_string(obj_with_verbs, passive_it);
02010                 }
02011                 
02012                 col = cur_verb->color;
02013 
02015 
02016                 print_x_centered_line_of_text(text,
02017                                               left_border,right_border,
02018                                               centered_y,
02019                                               surf_of_letter, screen,
02020                                               col);
02021 
02022                 rect = create_rect(left_border, y_top,  right_border, y_top + ht_per_verb);
02023 
02024                 choices.push_back(NEW(dialog_choice_verb_object(cur_verb, obj_with_verbs, passive_it, rect)));
02025 
02026 
02027                 // BEGIN draw mouseover highlight
02028                 if ( left_border <= mouse.x && mouse.x < right_border
02029                      &&
02030                      y_top <= mouse.y && mouse.y < y_bottom)
02031                 {
02032             
02033                     rectangleRGBA(screen, 
02034                                   left_border, y_top, right_border, y_bottom, 
02035                                   200, 100, 100, 200); 
02036                 }
02037                 // END
02038             }
02039         }
02040     }
02041 
02042 
02043 
02044     // BEGIN print none_of_the_above, if present
02045     if ( (pt_cast(item1, obj_with_verbs) && obj_with_verbs->none_of_the_above)
02046          ||
02047          (pt_cast(item2, obj_with_verbs) && obj_with_verbs->none_of_the_above))
02048     {
02049         y_top = ht_label + (num_choices -2) * ht_per_verb;
02050         y_bottom = ht_label + ( num_choices -1)* ht_per_verb;
02051 
02052         centered_y = y_top + (ht_per_verb - ht_of_letter)/2;
02053 
02054         text = "Other"; 
02055 
02056         col = color_of_none_of_the_above;
02057 
02059 
02060         print_x_centered_line_of_text(text,
02061                                       left_border,right_border,
02062                                       centered_y,
02063                                       surf_of_letter, screen,
02064                                       col);
02065         rect = create_rect(left_border, y_top,  right_border, y_top + ht_per_verb);
02066         
02067         choices.push_back(NEW(dialog_choice_double_other(rect)));
02068 
02069         // BEGIN draw mouseover highlight
02070         if ( left_border <= mouse.x && mouse.x < right_border
02071              &&
02072              y_top <= mouse.y && mouse.y < y_bottom)
02073         {
02074             
02075             rectangleRGBA(screen, 
02076                           left_border, y_top, right_border, y_bottom, 
02077                           200, 100, 100, 200); 
02078         }
02079         // END
02080         
02081     }
02082     // END
02083 
02084 
02085 
02086     // BEGIN print cancel button
02087 
02088     y_top =  ht_label + (num_choices-1) * ht_per_verb;
02089 
02090     centered_y = y_top + (ht_per_verb - ht_of_letter)/2;
02091 
02092     ht = draw_text_multiline_variable_ht( "Cancel",
02093                                           screen,
02094                                           left_border,
02095                                           centered_y,
02096                                           right_border,
02097                                           surf_of_letter,
02098                                           calc_rect_only, 
02099                                           color_of_less_important_text);
02100     rect = create_rect( left_border, y_top, right_border, y_top + ht_per_verb);
02101 
02102     cancel_rect = rect;
02103     // BEGIN draw mouseover highlight
02104     if ( point_in_rect(mouse, cancel_rect))
02105     {
02106         rectangleRGBA(screen, 
02107                       left_border, y_top, right_border, y_top + ht_per_verb, 
02108                       200, 100, 100, 200);      
02109     }
02110     // END
02111     // END
02112 
02113 }
02114 
02115 
02116 pt<anim_frame>
02117 update_still_anim(
02118     pt<PS_still_and_parsing> st,
02119     float dt)
02120 {
02121     // BEGIN decl
02122     pt<anim_frame> cur_fr;
02123     // END
02124 
02125     if(st->cur_frame >= st->anim->frames.size())
02126     {
02127         return st->anim->frames.back();
02128     }
02129     else
02130     {
02131         cur_fr = st->anim->frames[st->cur_frame];
02132 
02133         st->timer += dt;
02134         if (st->timer <= cur_fr->duration)
02135         {
02136             return cur_fr;
02137         }
02138         else
02139         {
02140             st->timer -= cur_fr->duration;
02141             st->cur_frame ++;
02142 
02143             if(st->cur_frame >= st->anim->frames.size())
02144             {
02145                 return st->anim->frames.back();
02146             }
02147             else
02148             {
02149                 return st->anim->frames[st->cur_frame];
02150             }
02151 
02152         }
02153     }
02154 }
02155 
02156 
02157 void
02158 FACK::execute_commands(
02159     pt<PC> pl,
02160     const list<pt<script_cmd> > & commands)
02161 {
02162     // BEGIN decl
02163     pt<PS_still_and_parsing> still;
02164     pt<anim_frame> cur_frame;
02165     result_exec_next_scr_cmd res;
02166     bool cast_ok;
02167     // END
02168 
02169     cast_ok = pt_cast(pl->state, still);
02170     assert(cast_ok);
02171     
02172 
02173     if(still->cur_frame >= still->anim->frames.size())
02174     {
02175         assert(still->anim->frames.size()>0);
02176         cur_frame =  still->anim->frames.back();
02177     }
02178     else
02179     {
02180         cur_frame =  still->anim->frames[still->cur_frame];
02181     }
02182 
02183 
02184     res = exec_next_scr_cmd(*vector_of(commands), 
02185                             0/*cur cmd*/,
02186                             pl,
02187                             cur_frame,
02188                             false/*do not increm step at start*/,
02189                             true /* at the end of the script, set the
02190                                   * player direction left or right,
02191                                   * unless the script explicitely says
02192                                   * not to */);
02193 
02194     pl->state = res.new_pl_state;
02195     pl->pos = res.new_pl_pos;
02196     pl->cur_dir = res.new_pl_dir;
02197     
02198 }
02199 
02200 
02201 
02202 struct speech_finished{};
02203 
02204 void 
02205 decide_position_for_text(
02206     string text,
02207     int_pair player_head,
02208     int & x_left, 
02209     int & y_top,
02210     int & x_right,
02211     const surf_of_letter_t & surf_of_letter,
02212     SDL_Surface * screen)
02213 {
02214     // BEGIN decl
02215     int ideal_wt, ht;
02216     int ideal_x_left, ideal_x_right;
02217     int real_x_left, real_x_right;
02218     int vert_gap_head_text;
02219     rgb col(0,0,0);
02220     // END
02221 
02222     vert_gap_head_text = 10;
02223     ideal_wt = screen->w * 2 / 3;
02224 
02225     ideal_x_left = player_head.x - ideal_wt/2;
02226     ideal_x_right = player_head.x + ideal_wt/2;
02227 
02228     if(ideal_x_left < 0)
02229     {
02230         real_x_left = 0;
02231         real_x_right = ideal_wt;
02232     }
02233     else if (ideal_x_right >= screen->w)
02234     {
02235         real_x_right = screen->w;
02236         real_x_left = real_x_right - ideal_wt;
02237     }
02238     else
02239     {
02240         real_x_right = ideal_x_right;
02241         real_x_left = ideal_x_left;
02242     }
02243 
02244     ht = draw_text_multiline_variable_ht(
02245         text, screen, real_x_left, 0, real_x_right, surf_of_letter, true, col);
02246 
02247     if (ht < player_head.y - vert_gap_head_text)
02248     {
02249         y_top = player_head.y - vert_gap_head_text -ht;
02250         x_left = real_x_left;
02251         x_right = real_x_right;
02252     }
02253     else
02254     {
02255         ht = draw_text_multiline_variable_ht(
02256             text, screen, 0, 0, screen->w, surf_of_letter, true, col);
02257 
02258         y_top = std::max(0, player_head.y - ht - vert_gap_head_text);
02259         x_left = 0;
02260         x_right = screen->w;
02261     }
02262 
02263 }
02264 
02265 
02266 variant<speech_finished, sentence_with_location>
02267 update_speech(
02268     AI_substate_speaking_while_standing & state,
02269     float dt,
02270     const surf_of_letter_t & surf_of_letter,
02271     SDL_Surface * screen,
02272     pt<anim_frame> & new_frame /*out*/,
02273     rgb text_color,
02274     bool time_frozen,
02275     const pt<PC> player,
02276     const room_scaling_data & scaling_data,
02277     int_pair top_left_of_screen_in_bg)
02278 {
02279     // BEGIN decl
02280     variant<speech_finished, sentence_with_location> ret;
02281     float change_seconds;
02282     string cur_txt;
02283     int x_left, y_top, x_right;
02284     pt<anim_frame> cur_frame;
02285     int_pair player_head_bg_coord;
02286     int_pair player_head_screen_coord;
02287     // END
02288 
02289   
02290     // BEGIN the purpose is to calculate new_frame.
02291     if(state.cur_frame_it >= state.current_phrase->anim->frames.size())
02292     {
02293         // the animation has finished. Return the last frame.
02294         new_frame = state.current_phrase->anim->frames.back();
02295     }
02296     else
02297     {
02298         if (time_frozen)
02299         {
02300             new_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02301         }
02302         else
02303         {
02304 
02305             // the animation has not finished. See if you have to change
02306             // frame
02307             cur_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02308 
02309             state.anim_timer += dt;
02310 
02311             if (state.anim_timer <= cur_frame->duration)
02312             {
02313                 // I don't have to change frame. Return the cur_frame
02314                 new_frame = cur_frame;
02315             }
02316             else
02317             {
02318                 // I have to change frame, and check AGAIN if the
02319                 // animation has finished.
02320                 state.anim_timer -= cur_frame->duration;
02321                 state.cur_frame_it ++;
02322                 if (state.cur_frame_it >= state.current_phrase->anim->frames.size())
02323                 {
02324                     // animation finished
02325                     new_frame = state.current_phrase->anim->frames.back();
02326                 }
02327                 else
02328                 {
02329                     new_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02330                 }
02331             }
02332         }
02333     }
02334     // END
02335        
02336     player_head_bg_coord.x = player->pos.x;
02337     player_head_bg_coord.y = player->pos.y - 
02338         int(float( new_frame->h  ) * 
02339             scaling_of_char(float(player->pos.y), scaling_data));
02340 
02341     player_head_screen_coord = player_head_bg_coord - top_left_of_screen_in_bg;
02342 
02343     cur_txt = state.current_phrase->str;
02344     if(time_frozen)
02345     {
02346         decide_position_for_text(cur_txt, player_head_screen_coord,
02347                                  x_left /*out*/,
02348                                  y_top /*out*/, x_right/*out*/, 
02349                                  surf_of_letter, screen);
02350         return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02351     }
02352     else
02353     {
02354         change_seconds = cur_txt.size() * 0.04f + 0.5f; // @@
02355 
02356         state.speech_timer += dt;
02357 
02358         if (state.speech_timer <= change_seconds)
02359         {
02360             decide_position_for_text(cur_txt, player_head_screen_coord, 
02361                                      x_left /*out*/,
02362                                      y_top /*out*/, x_right/*out*/, surf_of_letter, screen);
02363 
02364             return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02365         }
02366         else
02367         {
02368             state.speech_timer -= change_seconds;
02369             state.current_phrase ++;
02370 
02371 
02372             if (state.current_phrase == state.speech.end())
02373             {
02374 
02375                 // the previously calculated new_frame is ok.
02376 
02377                 return speech_finished();
02378             }
02379             else
02380             {
02381 
02382                 // BEGIN the sentence has changed. We have to change the
02383                 // animation frame as well, because speech is "dominant"
02384                 // over animation. Therefore we have to override the
02385                 // previously calculated new_frame.
02386                 state.cur_frame_it = 0; //state.current_phrase->anim->begin();
02387                 assert(state.current_phrase->anim->frames.size()>0);
02388                 new_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02389                 // END
02390 
02391                 decide_position_for_text(cur_txt, player_head_screen_coord, x_left /*out*/,
02392                     y_top /*out*/, x_right/*out*/, surf_of_letter, screen);
02393                 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02394             }
02395         }
02396 
02397     }
02398     assert(false);
02399 
02400 }
02401 
02402 
02403 variant<speech_finished, sentence_with_location>
02404 update_speech(
02405     AI_substate_speaking_while_sitting & state,
02406     float dt,
02407     const surf_of_letter_t & surf_of_letter,
02408     SDL_Surface * screen,
02409     const pt<anim_frame> const_frame,
02410     rgb text_color,
02411     bool time_frozen,
02412     const pt<PC> player,
02413     const room_scaling_data & scaling_data,
02414     int_pair top_left_of_screen_in_bg)
02415 {
02416     // BEGIN decl
02417     variant<speech_finished, sentence_with_location> ret;
02418     float change_seconds;
02419     string cur_txt;
02420     int x_left, y_top, x_right;
02421     pt<anim_frame> cur_frame;
02422     int_pair player_head_screen_coord;
02423     int_pair player_head_bg_coord;
02424     // END
02425 
02426   
02427        
02428     player_head_bg_coord.x = player->pos.x;
02429     // do not scale because I am sitting
02430     player_head_bg_coord.y = player->pos.y - int(float( const_frame->h  ) );
02431 
02432     player_head_screen_coord = player_head_bg_coord - top_left_of_screen_in_bg;
02433 
02434     cur_txt = *state.current_phrase;
02435     if(time_frozen)
02436     {
02437         decide_position_for_text(cur_txt, player_head_screen_coord, x_left /*out*/,
02438             y_top /*out*/, x_right/*out*/, surf_of_letter, screen);
02439         return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02440     }
02441     else
02442     {
02443         change_seconds = cur_txt.size() * 0.04f + 0.5f;
02444 
02445         state.speech_timer += dt;
02446 
02447         if (state.speech_timer <= change_seconds)
02448         {
02449             decide_position_for_text(cur_txt, player_head_screen_coord, x_left /*out*/,
02450                 y_top /*out*/, x_right/*out*/, surf_of_letter, screen);
02451 
02452             return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02453         }
02454         else
02455         {
02456             state.speech_timer -= change_seconds;
02457             state.current_phrase ++;
02458 
02459 
02460             if (state.current_phrase == state.speech.end())
02461             {
02462 
02463                 // the previously calculated new_frame is ok.
02464 
02465                 return speech_finished();
02466             }
02467             else
02468             {
02469                 decide_position_for_text(cur_txt, player_head_screen_coord, x_left /*out*/,
02470                     y_top /*out*/, x_right/*out*/, surf_of_letter, screen);
02471                 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02472             }
02473         }
02474 
02475     }
02476     assert(false);
02477 
02478 }
02479 
02480 template<class T>
02481 void
02482 list_remove_one( T & l, typename T::value_type el)
02483 {
02484     // BEGIN decl
02485     typename T::iterator i;
02486     bool done;
02487     // END
02488     done = false;
02489     for(i = l.begin() ; i != l.end(); i++)
02490     {
02491         if (*i == el)
02492         {
02493             i = l.erase(i);
02494             done = true;
02495             break;
02496         }
02497     }
02498     assert(done);
02499 }
02500 
02501 
02502 result_exec_next_scr_cmd
02503 end_commands(
02504     pt<PC> pl,
02505     int cur_cmd_it,
02506     bool must_set_player_left_or_right)
02507 {
02508     // BEGIN decl
02509     direction dir2;
02510     pt<still_situation_normal> normal;
02511     pt<still_situation_sitting> sitting;
02512     bool ok;
02513     // END
02514 
02515 
02516     if (must_set_player_left_or_right)
02517     {
02518         if(pl->cur_dir == d_left)
02519             dir2 = d_left;
02520         else
02521             dir2 = d_right;
02522     }
02523     else
02524     {
02525         dir2 = pl->cur_dir;
02526     }
02527 
02528 
02529     if(pt_cast(pl->still_situat, normal))
02530     {
02531         return result_exec_next_scr_cmd(
02532             NEW( PS_missing_two_items(
02533                      map_get(pl->anim_of_norm_still_sit,
02534                              dir2),
02535                      0, 
02536                      0)),
02537             cur_cmd_it,
02538             pl->pos,
02539             dir2);
02540     }
02541     else
02542     {
02543         ok = pt_cast(pl->still_situat, sitting);
02544         assert(ok);
02545         
02546         return result_exec_next_scr_cmd(
02547             NEW( PS_missing_two_items(
02548                      map_get(pl->anim_of_sitting_still_sit,
02549                              sitting->situation_name),
02550                      0, 
02551                      0)),
02552             cur_cmd_it,
02553             pl->pos,
02554             dir2);
02555     }
02556 
02557 }
02558 
02559 
02560 
02561 void
02562 FACK::stand_up_if_sitting(
02563     pt<PC> pl)
02564 {
02565 
02566     // BEGIN decl
02567     pt<still_situation_sitting> sitting;
02568     // END
02569 
02570 
02571     // BEGIN automatically stand up from chairs
02572     if (pt_cast(pl->still_situat, sitting))
02573     {
02574         pl->loc->occupied_sitting_places.erase(sitting->occupied_place);
02575         pl->still_situat = NEW(still_situation_normal());
02576     }
02577     // END
02578 
02579 }
02580 
02581 void
02582 FACK::close_all_open_popups(
02583     const pt<PC> pl)
02584 {
02585     // BEGIN decl
02586     list<pt<popup> >::iterator co;
02587     // END
02588 
02589 
02590     pl->open_popups.clear();
02591 }
02592 
02593 // recursive
02594 result_exec_next_scr_cmd
02595 FACK::exec_next_scr_cmd(
02596     const vector<pt<script_cmd> > commands,
02597     int cur_cmd_it,
02598     const pt<PC> pl,
02599     pt<anim_frame> last_frame,
02600     bool increm_cmd_at_start,
02601     bool must_set_player_left_or_right)
02602 {
02603     // BEGIN decl
02604     direction dir2;
02605     still_situation still_sit;
02606     pt<PS_governed_by_AI> gov_ai;
02607     variant < no_route_found, pt<list<int_pair> > > maybe_route;
02608     pt<list<int_pair> > route;
02609     pt<list<int_pair> > route2;
02610     pt<scr_cmd_walk> cmd_walk;   
02611     pt<scr_cmd_speak> cmd_speak;   
02612     pt<scr_cmd_set_sitting_state> set_sitting_still_stat;   
02613     pt<scr_cmd_passive_anim> cmd_passive_anim;   
02614     pt<scr_cmd_light_transition> cmd_light_transit;   
02615     pt<scr_cmd_wait_for_person_to_stop_talking> cmd_wait_stop_talk;   
02616     pt<scr_cmd_change_light> cmd_change_light;   
02617     pt<scr_cmd_change_loc> cmd_change_loc;   
02618     pt<scr_cmd_modify_zone> cmd_modify_zone;   
02619     pt<scr_cmd_add_to_container> cmd_add_to_cont;   
02620     pt<scr_cmd_add_to_container_in_pos> cmd_add_to_cont_in_pos;   
02621     pt<scr_cmd_remove_from_container> cmd_remove_from_cont;
02622     pt<scr_cmd_modify_layer> cmd_modify_layer;   
02623     pt<scr_cmd_quick_message> quick_mess;   
02624     pt<scr_cmd_look_at_fixed_direction> cmd_look_at_dir;   
02625     speech_t::const_iterator i;
02626     speech2_t sp2;
02627     horizontal_dir d;
02628     pt<script_cmd> cur_cmd;
02629     pt<still_situation_normal> normal;
02630     pt<still_situation_sitting> sitting;
02631     list<string> strings;
02632     pt<scr_cmd_open_popup> open_popup;
02633     bool ok;
02634     pt<container> real_co;
02635     int_pair pos;
02636     // END
02637 
02638     if(increm_cmd_at_start)
02639         cur_cmd_it ++;
02640 
02641     if(cur_cmd_it >= commands.size())
02642     {
02643         return end_commands(pl, cur_cmd_it, must_set_player_left_or_right);
02644     }
02645     else
02646     {
02647         cur_cmd = commands[cur_cmd_it];
02648         // initialize gov_ai->substate = NEW(...the next substate...)
02649 
02650         if(pt_cast(cur_cmd, cmd_walk))
02651         {
02652             if(!( pl->pos == cmd_walk->dest))
02653             {
02654                 maybe_route = best_route(
02655                     pl->pos, cmd_walk->dest, *pl->loc->walking_map);
02656 
02657                 ok = var_cast(maybe_route, route); 
02658                 assert(ok); 
02659 
02660                 route2 = compute_feet_positions(
02661                     pl->pos, *route, pl->loc->scaling_data,
02662                     pl->walk_step_horiz, pl->walk_step_vert);
02663                 assert(route2->size()>0);
02664                 dir2 = compute_dir(pl->pos, 
02665                                    route2->front(), pl->walk_step_horiz);
02666                 
02667                 stand_up_if_sitting(pl);
02668                 close_all_open_popups(pl);
02669 
02670                 return result_exec_next_scr_cmd(
02671                     NEW(PS_governed_by_AI(
02672                             commands,
02673                             cur_cmd_it,
02674                             NEW(AI_substate_walk(*vector_of(*route2))))),
02675                     cur_cmd_it,
02676                     pl->pos,
02677                     dir2);
02678             }
02679             else
02680             {
02681                 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02682             }
02683         }
02684         else if(pt_cast(cur_cmd, cmd_speak))
02685         {
02686             if(cmd_speak->close_containers == close_any_open_container)
02687             {
02688                 close_all_open_popups(pl);
02689             }
02690 
02691             if (pt_cast(pl->still_situat, sitting))
02692             {
02693                 setof_(
02694                     i->str,
02695                     i, 
02696                     cmd_speak->speech,
02697                     true,
02698                     strings);
02699  
02700                 return result_exec_next_scr_cmd(
02701                     NEW(PS_governed_by_AI(
02702                             commands,
02703                             cur_cmd_it,
02704                             NEW(AI_substate_speaking_while_sitting(strings, last_frame)))),
02705                     cur_cmd_it,
02706                     pl->pos,
02707                     pl->cur_dir);
02708             }
02709             else
02710             {
02711                 if(pl->cur_dir == d_left)
02712                 {
02713                     d = hd_left;
02714                 }
02715                 else
02716                 {
02717                     pl->cur_dir = d_right;
02718                     d = hd_right;
02719                 }
02720             
02721                 setof_(
02722                     anim_and_string( 
02723                         map_get(pl->anim_of_mood, 
02724                                 i->mood).get_anim(d), i->str),
02725                     i, 
02726                     cmd_speak->speech,
02727                     true,
02728                     sp2);
02729 
02730                 return result_exec_next_scr_cmd(
02731                     NEW(PS_governed_by_AI(
02732                             commands,
02733                             cur_cmd_it,
02734                             NEW(AI_substate_speaking_while_standing(sp2)))),
02735                     cur_cmd_it,
02736                     pl->pos,
02737                     pl->cur_dir);
02738             }
02739 
02740         }
02741         else if(pt_cast(cur_cmd, cmd_passive_anim))
02742         {
02743             close_all_open_popups(pl);
02744 
02745             return result_exec_next_scr_cmd(
02746                 NEW(PS_governed_by_AI(
02747                         commands,
02748                         cur_cmd_it,
02749                         NEW(AI_substate_passive_anim(cmd_passive_anim->anim)))),
02750                 cur_cmd_it,
02751                 pl->pos,
02752                 pl->cur_dir);
02753         }
02754         else if(pt_cast(cur_cmd, cmd_wait_stop_talk))
02755         {
02756             return result_exec_next_scr_cmd(
02757                 NEW(PS_governed_by_AI(
02758                         commands,
02759                         cur_cmd_it,
02760                         NEW(AI_substate_waiting_for_person_to_stop_talking(cmd_wait_stop_talk->person,
02761                                                                            last_frame)))),
02762                 cur_cmd_it,
02763                 pl->pos,
02764                 pl->cur_dir);
02765         }
02766         else if(pt_cast(cur_cmd, cmd_change_light))
02767         {
02768             if (cmd_change_light->turn_on)
02769             {
02770                 // @@ if light was not already switched on in the
02771                 // meantime
02772                 cmd_change_light->loc->active_lights.insert(cmd_change_light->ligh);
02773             }
02774             else
02775             {
02776                 // @@ if light is not already switched off
02777                 cmd_change_light->loc->active_lights.erase(cmd_change_light->ligh);
02778             }
02779             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02780         }
02781         else if(pt_cast(cur_cmd, open_popup))
02782         {
02783             pl->open_popups.push_back(open_popup->dr);
02784 
02785             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02786         }
02787         else if(pt_cast(cur_cmd, quick_mess))
02788         {
02789             quick_msg = NEW(quick_message(quick_mess->text));
02790 
02791             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02792         }
02793         else if(pt_cast(cur_cmd, set_sitting_still_stat))
02794         {
02795             if (! in( set_sitting_still_stat->occupied_place, pl->loc->occupied_sitting_places))
02796             {
02797                 pl->still_situat = NEW(still_situation_sitting(
02798                                            set_sitting_still_stat->situation_name,
02799                                            set_sitting_still_stat->occupied_place));
02800                 pl->loc->occupied_sitting_places.insert(set_sitting_still_stat->occupied_place);
02801                 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02802             }
02803             else
02804             {
02805                 // @@ output message
02806                 cout << "The place is occupied" << endl;
02807                 return end_commands(pl, cur_cmd_it, must_set_player_left_or_right);
02808             }
02809         }
02810         else if(pt_cast(cur_cmd, cmd_change_loc))
02811         {
02812             pl->loc = cmd_change_loc->new_loc;
02813             pl->pos = cmd_change_loc->position;
02814 
02815             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02816         }
02817         else if(pt_cast(cur_cmd, cmd_light_transit))
02818         {
02819 
02820             this->transitions_of_fixed_light.push_back(
02821                 NEW(transition_of_fixed_light( cmd_light_transit->ligh,
02822                                                cmd_light_transit->time_delta,
02823                                                cmd_light_transit->start_intensity,
02824                                                cmd_light_transit->dest_intensity,
02825                                                cmd_light_transit->switch_off_light_at_the_end)));
02826             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02827         }
02828         else if(pt_cast(cur_cmd, cmd_add_to_cont))
02829         {
02830             if(contains_recursively(cmd_add_to_cont->cont,
02831                                     cmd_add_to_cont->object,
02832                                     real_co /* out */, 
02833                                     pos /* out */))
02834             {
02835                 raise_exception("Error in game logic: the item was already in the inventory.");
02836             }
02837             else
02838             {
02839                 cmd_add_to_cont->cont->add_item(cmd_add_to_cont->object);
02840                 
02841                 if (cmd_add_to_cont->cont == act_pl->cache)
02842                 {
02843                     game_state = NEW(game_state_flashing_inv_t(cmd_add_to_cont->object));
02844                 }
02845             }
02846             
02847             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02848 
02849         }
02850         else if(pt_cast(cur_cmd, cmd_add_to_cont_in_pos))
02851         {
02852             if(contains_recursively(cmd_add_to_cont_in_pos->cont,
02853                                     cmd_add_to_cont_in_pos->object,
02854                                     real_co /* out */, 
02855                                     pos /* out */))
02856             {
02857                 raise_exception("Error in game logic: the item was already in the inventory.");
02858             }
02859             else
02860             {
02861                 cmd_add_to_cont_in_pos->cont->add_item_in_pos(
02862                     pos_and<pt<obj_or_concept> > (cmd_add_to_cont_in_pos->object,
02863                                                   cmd_add_to_cont_in_pos->pos));
02864                 
02865                 if (cmd_add_to_cont_in_pos->cont == act_pl->cache)
02866                 {
02867                     game_state = NEW(game_state_flashing_inv_t(cmd_add_to_cont_in_pos->object));
02868                 }
02869             }
02870             
02871             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02872 
02873         }
02874         else if(pt_cast(cur_cmd, cmd_remove_from_cont))
02875         {
02876             cmd_remove_from_cont->cont->remove_item_recursively(cmd_remove_from_cont->object);
02877             
02878             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02879 
02880         }
02881         else if(pt_cast(cur_cmd, cmd_modify_zone))
02882         {
02883             if(cmd_modify_zone->show == HIDE)
02884                 cmd_modify_zone->zone->visible = false;
02885             else
02886                 cmd_modify_zone->zone->visible = true;
02887 
02888             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02889 
02890         }
02891         else if(pt_cast(cur_cmd, cmd_modify_layer))
02892         {
02893             if(cmd_modify_layer->show == HIDE)
02894                 cmd_modify_layer->layer->visible = false;
02895             else
02896                 cmd_modify_layer->layer->visible = true;
02897 
02898 
02899             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02900 
02901         }
02902         else if(pt_cast(cur_cmd, cmd_look_at_dir))
02903         {
02904             pl->cur_dir = cmd_look_at_dir->dir;
02905 
02906             return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, 
02907                                      false /* do not set the player direction left or right at the end of the script */);
02908         }
02909         else
02910         {
02911             assert(false);
02912         }
02913 
02914     }
02915 }
02916 
02917 
02918 
02919 
02920 
02921 update_AI_result
02922 FACK::update_AI_state(
02923     pt<PC> pl,
02924     float dt, 
02925     int_pair top_left_of_screen_in_bg)
02926 {
02927 
02928     // BEGIN decl
02929     pt<script_cmd> cur_cmd;
02930     pt<script_cmd> cur_cmd_other;
02931 
02932     pt<scr_cmd_walk> cmd_walk;
02933 
02934     pt<AI_substate_walk> walk;
02935     pt<AI_substate_waiting_for_person_to_stop_talking> wait_stop_talk;
02936     pt<AI_substate_speaking_while_standing> speaking_standing;
02937     pt<AI_substate_speaking_while_sitting> speaking_sitting;
02938 
02939     pt<AI_substate_passive_anim> passive_anim;
02940     pair<int_pair, direction> new_pos;
02941     pt<PS_governed_by_AI> gov_ai;
02942     pt<PS_governed_by_AI> gov_ai_other;
02943     //pt<obj> it;
02944     seq_list<pt<bg_hot_zone> >::const_iterator x;
02945     pt<anim_frame> cur_frame;
02946     variant<walking_finished, pair<int_pair, direction> > maybe_new_pos;
02947     variant<speech_finished, sentence_with_location> maybe_sentence;
02948     pt<game_state_flashing_inv_t> flashing_inv;
02949     bool ok;
02950     result_exec_next_scr_cmd res;
02951     // END
02952 
02953 
02954     ok = pt_cast(pl->state, gov_ai);
02955     assert(ok);
02956 
02957     if (pt_cast(gov_ai->substate, walk))
02958     {
02959         cur_frame = map_get( pl->walk_frame_when,
02960             walk_frame_id( walk->cur_foot, 
02961                 walk->cur_phase, pl->cur_dir));
02962 
02963         if(pt_cast(game_state, flashing_inv))
02964         {
02965 
02966             return update_AI_result( cur_frame, pl->pos, pl->cur_dir,
02967                 no_sentence(), pl->state);
02968         }
02969         else
02970         {
02971             maybe_new_pos = update_walking_animation(
02972                 cur_frame->duration, 
02973                 walk /* mod */, pl->pos, pl->walk_step_horiz, dt, pl->cur_dir);
02974             
02975             // I have to call this again, because
02976             // update_walking_animation has changed step_walk
02977             cur_frame = map_get( pl->walk_frame_when, 
02978                 walk_frame_id( walk->cur_foot, 
02979                     walk->cur_phase, pl->cur_dir));
02980 
02981             if (var_cast(maybe_new_pos, new_pos))
02982             {
02983                 return update_AI_result( cur_frame, new_pos.first, 
02984                     new_pos.second, no_sentence(), pl->state);
02985             }
02986             else
02987             { 
02988                 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl, cur_frame, true, 
02989                                         true /* by default, reset pl direction*/);
02990 
02991                 return update_AI_result( cur_frame, res.new_pl_pos, res.new_pl_dir,
02992                                          no_sentence(), res.new_pl_state);
02993             }
02994         }
02995 
02996 
02997     }
02998     else if (pt_cast(gov_ai->substate, passive_anim))
02999     {
03000         assert (passive_anim->cur_frame < passive_anim->anim->frames.size());
03001 
03002         cur_frame = passive_anim->anim->frames[passive_anim->cur_frame];
03003 
03004         if (pt_cast(game_state, flashing_inv))
03005         {
03006 
03007             return update_AI_result( 
03008                 cur_frame, pl->pos,
03009                 pl->cur_dir, no_sentence(), pl->state);
03010         }
03011         else
03012         {
03013             passive_anim->timer += dt;
03014             
03015             if(passive_anim->timer <= cur_frame->duration)
03016             {
03017                 return update_AI_result( cur_frame,
03018                                          pl->pos, pl->cur_dir, no_sentence(), pl->state);
03019             }
03020             else
03021             {
03022                 passive_anim->timer -= cur_frame->duration;
03023                 passive_anim->cur_frame ++;
03024                 if (passive_anim->cur_frame >= passive_anim->anim->frames.size())
03025                 {
03026                     res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl, 
03027                                             cur_frame, true, true /* by default, set pl dir left or right */);
03028 
03029                     return update_AI_result( cur_frame /* @ ok?*/,
03030                                              res.new_pl_pos, res.new_pl_dir,
03031                                              no_sentence(), res.new_pl_state);
03032                 }
03033                 else
03034                 {
03035                     cur_frame =   passive_anim->anim->frames[passive_anim->cur_frame];
03036 
03037                     return update_AI_result( cur_frame, pl->pos,
03038                                              pl->cur_dir, no_sentence(), pl->state);
03039                 }
03040             }
03041         }
03042     }
03043     else if (pt_cast(gov_ai->substate, speaking_standing))
03044     {
03045         
03046         maybe_sentence = update_speech(*speaking_standing, dt, 
03047                                        surf_of_letter, screen, cur_frame /*out*/, pl->text_color, 
03048                                        pt_cast(game_state, flashing_inv) /*time frozen */,
03049                                        pl, pl->loc->scaling_data,
03050                                        top_left_of_screen_in_bg);
03051             
03052         sentence_with_location sentenc;
03053         if(var_cast(maybe_sentence, sentenc))
03054         {
03055 
03056             return update_AI_result(  cur_frame, pl->pos,
03057                 pl->cur_dir, sentenc, pl->state);
03058         }
03059         else
03060         {
03061             if (pt_cast(game_state, flashing_inv))
03062             {
03063 
03064                 return update_AI_result(  cur_frame, pl->pos, 
03065                     pl->cur_dir, no_sentence(), pl->state);
03066             }
03067             else
03068             {
03069                 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl, 
03070                                         cur_frame, true, true /* by default, set pl dir left or right */);
03071 
03072                 return update_AI_result( cur_frame,
03073                                          res.new_pl_pos, res.new_pl_dir,
03074                                          no_sentence(), res.new_pl_state);
03075             }
03076         }
03077 
03078 
03079     }
03080     else if (pt_cast(gov_ai->substate, speaking_sitting))
03081     {
03082         
03083         maybe_sentence = update_speech(*speaking_sitting, dt, 
03084                                        surf_of_letter, screen, speaking_sitting->frame, 
03085                                        pl->text_color, 
03086                                        pt_cast(game_state, flashing_inv) /*time frozen */,
03087                                        pl, pl->loc->scaling_data,
03088                                        top_left_of_screen_in_bg);
03089             
03090         sentence_with_location sentenc;
03091         if(var_cast(maybe_sentence, sentenc))
03092         {
03093 
03094             return update_AI_result(  speaking_sitting->frame, pl->pos,
03095                                       pl->cur_dir, sentenc, pl->state);
03096         }
03097         else
03098         {
03099             if (pt_cast(game_state, flashing_inv))
03100             {
03101 
03102                 return update_AI_result(  speaking_sitting->frame, pl->pos, 
03103                                           pl->cur_dir, no_sentence(), pl->state);
03104             }
03105             else
03106             {
03107                 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl, 
03108                                         speaking_sitting->frame, true,
03109                                         true /* by default, set pl dir left or right */);
03110 
03111                 return update_AI_result( speaking_sitting->frame,
03112                                          res.new_pl_pos, res.new_pl_dir,
03113                                          no_sentence(), res.new_pl_state);
03114             }
03115         }
03116 
03117 
03118     }
03119     else if (pt_cast(gov_ai->substate, wait_stop_talk))
03120     {
03121         if(pt_cast(wait_stop_talk->person->state, gov_ai_other))
03122         {
03123             if( pt_cast(gov_ai_other->substate, speaking_sitting) 
03124                 ||
03125                 pt_cast(gov_ai_other->substate, speaking_standing))
03126             {
03127                 // the other person is still talking
03128 
03129                 return update_AI_result(  wait_stop_talk->frame, pl->pos,
03130                     pl->cur_dir, no_sentence(), pl->state);
03131             }
03132             else
03133             {
03134                 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl, 
03135                                         wait_stop_talk->frame, true, 
03136                                         true /* by default, set pl dir left or right */);
03137 
03138                 return update_AI_result( wait_stop_talk->frame,
03139                                          res.new_pl_pos, res.new_pl_dir,
03140                                          no_sentence(), res.new_pl_state);
03141             }
03142         }
03143         else
03144         {
03145             // the other person is no more in AI state, so he is not
03146             // talking. Advance.
03147             res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, 
03148                                     pl, wait_stop_talk->frame, true, 
03149                                     true /* by default, set pl dir left or right */);
03150 
03151             return update_AI_result( wait_stop_talk->frame,
03152                                      res.new_pl_pos, res.new_pl_dir,
03153                                      no_sentence(), res.new_pl_state);
03154         }
03155 
03156 
03157     }
03158     else
03159     {
03160         if(!gov_ai->substate)
03161             assert(false);
03162         else
03163             assert(false);
03164     }
03165 
03166 }
03167 
03168 
03169 
03170 
03171 
03172 void
03173 FACK::manage_button_up(
03174     list<SDL_Event>::const_iterator ev)
03175 {
03176     // BEGIN decl
03177     // END
03178 
03179 
03180 }
03181 
03182 void
03183 zoomable::render(
03184     SDL_Surface * screen,
03185     const pt<game_state_t> game_state) const
03186 {
03187     // BEGIN decl
03188     SDL_Rect r;
03189     int ret;
03190     // END
03191 
03192 
03193     r.x = this->position_in_screen.x;
03194     r.y = this->position_in_screen.y;
03195 
03196     ret = SDL_BlitSurface(this->picture, NULL, screen, &r);
03197     assert(ret == 0);
03198 }
03199 
03200 
03201 void
03202 container::render(
03203     SDL_Surface * screen,
03204     const pt<game_state_t> game_state) const
03205 {
03206     // BEGIN decl
03207     SDL_Rect r;
03208     int ret;
03209     list<pos_and<pt<obj_or_concept> > >::const_iterator i;
03210     pt<game_state_flashing_inv_t> flashing;
03211     // END
03212 
03213 
03214     r.x = this->position_in_screen.x;
03215     r.y = this->position_in_screen.y;
03216 
03217     ret = SDL_BlitSurface(this->picture, NULL, screen, &r);
03218     assert(ret == 0);
03219     
03220     foreach(i, this->sorted_items){
03221 
03222         r.x = this->position_in_screen.x + i->pos.x;
03223         r.y = this->position_in_screen.y + i->pos.y;
03224 
03225         ret = SDL_BlitSurface(i->o->get_inv_surf(),
03226                               NULL,
03227                               screen, 
03228                               &r);
03229         assert (ret == 0);
03230 
03231 
03232         // BEGIN flashing
03233         if ( pt_cast(game_state, flashing) && 
03234              flashing->item_that_is_flashing == i->o /* @@ pointer equality */ &&
03235              int(floor(flashing->timer / 0.3f)) % 2 == 0)
03236         {
03237             rectangleRGBA(screen, 
03238 
03239                           this->position_in_screen.x + i->pos.x,
03240                           this->position_in_screen.y + i->pos.y,
03241                           
03242                           this->position_in_screen.x + i->pos.x + i->o->get_inv_surf()->w,
03243                           this->position_in_screen.y + i->pos.y + i->o->get_inv_surf()->h,
03244 
03245 
03246                           200, 100, 100, 200);
03247 
03248         }
03249         // END
03250 
03251     }
03252 
03253 }
03254 
03255 struct result_is_there_only_one_option{
03256         virtual ~result_is_there_only_one_option(){}
03257 };
03258 
03259 struct result_is_there_only_one_option_yes : public result_is_there_only_one_option
03260 {
03261         pt<verb> v;
03262         pt<phys_obj_with_verbs> obj_with_verb;
03263         pt<phys_obj> obj_without_verb;
03264         
03265         result_is_there_only_one_option_yes(
03266             pt<verb> v,
03267             pt<phys_obj_with_verbs> obj_with_verb,
03268             pt<phys_obj> obj_without_verb)
03269         {
03270             this->v = v;
03271             this->obj_with_verb = obj_with_verb;
03272             this->obj_without_verb = obj_without_verb;
03273         }
03274             
03275 };
03276 
03277 struct result_is_there_only_one_option_no : public result_is_there_only_one_option {};
03278 
03279 pt<result_is_there_only_one_option>
03280 is_there_only_one_option_overall(
03281     pt<phys_obj> o1,
03282     pt<phys_obj> o2)
03283 {
03284     // BEGIN decl
03285     pt<phys_obj_with_verbs> obj_with_verbs;
03286     int count;
03287     vector<pt<phys_obj> > objs;
03288     int c;
03289     pt<phys_obj> active_obj, passive_obj;
03290     pt<result_is_there_only_one_option> last_option;
03291     // END
03292 
03293     objs = *vector_of(ulist(o1) << o2);
03294 
03295     // BEGIN find count
03296     count = 0;
03297     last_option = NEW(result_is_there_only_one_option_no());
03298 
03299     for(c = 0; c < 2; c++)
03300     {
03301         active_obj = objs[c];
03302         passive_obj = objs[1-c];
03303         
03304         if(pt_cast(active_obj, obj_with_verbs))
03305         {
03306             count += obj_with_verbs->verbs.size();
03307             
03308             if (obj_with_verbs->none_of_the_above)
03309             {
03310                 count ++;
03311             }
03312             last_option = NEW(result_is_there_only_one_option_yes(
03313                                   obj_with_verbs->verbs.front(),
03314                                   obj_with_verbs,
03315                                   passive_obj));
03316         }
03317     }
03318     // END
03319 
03320     assert(count >0);
03321 
03322     if(count == 1)
03323     {
03324         return last_option;
03325     }
03326     else
03327     {
03328         return NEW(result_is_there_only_one_option_no());
03329     }
03330 
03331 }
03332 
03333 
03334 void
03335 FACK::the_obj_was_clicked(
03336     pt<obj_or_concept> item_chosen,
03337     int_pair mouse)
03338 {
03339     // BEGIN decl
03340     list<pt<dialog_choice> > choices;
03341     list<pt<dialog_choice> >::const_iterator cho;
03342 
03343     SDL_Rect cancel_rect;
03344     pt<PS_missing_two_items> missing_two_items;
03345     pt<PS_missing_one_item> missing_one_item;
03346     list<pt<phys_obj_with_verbs> >ambig;
03347     pt<popup> zoomab;
03348     list<pt<obj_or_concept> >::const_iterator am;
03349     // END
03350 
03351 
03352 
03353     if(pt_cast(item_chosen, zoomab))
03354     {
03355         if(!in_list(zoomab, act_pl->open_popups)) // @@ pointer equality
03356             act_pl->open_popups.push_back(zoomab);
03357         else
03358             list_remove_one(act_pl->open_popups, zoomab);
03359     }
03360     else
03361     {
03362         // an item has been clicked, either in the
03363         // room or in the inventory
03364 
03365         if (pt_cast(act_pl->state, missing_one_item))
03366         {
03367             // BEGIN decl
03368             pt<concept> conc;
03369             pt<phys_obj> phys1, phys2;
03370             pt<phys_obj_with_verbs> obj_with_verbs;
03371             pt<result_is_there_only_one_option> ret;
03372             pt<result_is_there_only_one_option_yes> only_one;
03373             // END
03374 
03375             if (pt_cast(item_chosen, conc) || pt_cast(missing_one_item->obj_already_chosen, conc))
03376             {
03377                 execute_action_object_object( item_chosen, missing_one_item->obj_already_chosen);
03378             }
03379             else
03380             {
03381                 phys1 = dynamic_pointer_cast<phys_obj> (item_chosen);
03382                 phys2 = dynamic_pointer_cast<phys_obj> (missing_one_item->obj_already_chosen);
03383                 assert(phys1);
03384                 assert(phys2);
03385 
03386 
03387                 if(pt_cast(phys1, obj_with_verbs) || pt_cast(phys2, obj_with_verbs))
03388                 {
03389                     ret = is_there_only_one_option_overall(phys1, phys2);
03390 
03391                     if (pt_cast(ret, only_one))
03392                     {
03393                         execute_action_verb_object(only_one->v, 
03394                                                    only_one->obj_without_verb /* obj for which the verb was not chosen*/,
03395                                                    only_one->obj_with_verb /* obj which had that verb in its verb list */);
03396                     }
03397                     else
03398                     {
03399                         draw_verb_dialog( 
03400                             phys1,
03401                             phys2,
03402                             surf_of_letter,
03403                             screen,
03404                             true /* calc_rect_only */, 
03405                             mouse, 
03406                             cancel_rect /* out*/,
03407                             choices /* out*/);
03408                     
03409                         act_pl->state = NEW( PS_choosing_verb(
03410                                                  phys1,
03411                                                  phys2 ,
03412                                                  choices,
03413                                                  cancel_rect,
03414                                                  missing_one_item->anim,
03415                                                  missing_one_item->timer,
03416                                                  missing_one_item->cur_frame));
03417                     }
03418                 }
03419                 else // no item is ambiguous 
03420                 { 
03421                     execute_action_object_object( phys1, phys2);
03422                 }
03423             }
03424         }
03425         else if (pt_cast(act_pl->state, missing_two_items))
03426         {
03427             act_pl->state = NEW( PS_missing_one_item(
03428                                      item_chosen, missing_two_items->anim,
03429                                      missing_two_items->timer,
03430                                      missing_two_items->cur_frame));
03431         }
03432     }
03433 
03434 }
03435 
03436 void
03437 FACK::cycle_active_player()
03438 {
03439     // BEGIN decl
03440     list<pt<PC> >::const_iterator ch;
03441     list< list<pt<PC> >::const_iterator  > qwe;
03442     // END
03443 
03444     setof_( ch, ch, players, *ch == act_pl, qwe);
03445     assert(qwe.size() == 1);
03446     ch = qwe.front();
03447     ch ++;
03448 
03449     if (ch == players.end())
03450     {
03451         act_pl = players.front();
03452     }
03453     else
03454     {
03455         act_pl = *ch;
03456     }
03457 
03458     active_player_changed(act_pl);
03459 
03460 }
03461 
03462 
03463 SDL_Rect
03464 FACK::find_scrolling_rect(
03465     int_pair size_of_bg_surf)
03466 {
03467     // BEGIN decl
03468     int ht_of_graphic_window, wt_of_graphic_window;
03469     int ideal_top, ideal_bottom, ideal_left, ideal_right;
03470     int final_top, final_bottom, final_left, final_right;
03471 
03472     // END
03473 
03474     ht_of_graphic_window = std::min( size_of_bg_surf.y,
03475                                      screen->h - act_pl->cache->picture->h - calc_command_bar_ht());
03476     wt_of_graphic_window = std::min( size_of_bg_surf.x,
03477                                      screen->w);
03478 
03479     ideal_top = act_pl->pos.y - ht_of_graphic_window * 3/4;
03480     ideal_bottom = act_pl->pos.y + ht_of_graphic_window / 4;
03481     ideal_left = act_pl->pos.x - wt_of_graphic_window /2;
03482     ideal_right = act_pl->pos.x + wt_of_graphic_window /2;
03483 
03484     if (ideal_left <0)
03485     {
03486         final_left = 0;
03487         final_right = wt_of_graphic_window;
03488     }
03489     else if (ideal_right > size_of_bg_surf.x)
03490     {
03491         final_right = size_of_bg_surf.x;
03492         final_left = final_right - wt_of_graphic_window;
03493     }
03494     else
03495     {
03496         final_left = ideal_left;
03497         final_right = ideal_right;
03498     }
03499                 
03500     if (ideal_top <0)
03501     {
03502         final_top = 0;
03503         final_bottom = ht_of_graphic_window;
03504     }
03505     else if (ideal_bottom > size_of_bg_surf.y)
03506     {
03507         final_bottom = size_of_bg_surf.y;
03508         final_top = final_bottom - ht_of_graphic_window;
03509     }
03510     else
03511     {
03512         final_top = ideal_top;
03513         final_bottom = ideal_bottom;
03514     }
03515 
03516     return create_rect( final_left, final_top, final_right, final_bottom);
03517 
03518 
03519 }
03520 
03521 void
03522 FACK::recompute_on_lights(
03523     set<pt<light> > & on_lights ) const
03524 {
03525     // BEGIN decl
03526     set<pt<light_across_loc> >::const_iterator lia;
03527     set<pt<light_fixed_in_loc> >::const_iterator lif;
03528     list<pt<PC> >::const_iterator pl;
03529     pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
03530     list<pos_and<pt<obj_or_concept> > >::const_iterator ob;
03531     // END
03532 
03533     on_lights.clear();
03534     foreach(lif, act_pl->loc->active_lights){
03535         on_lights.insert(*lif);
03536     }
03537 
03538     foreach(lia, lights_across_loc){
03539         if(   pt_cast(act_pl->drag_st, maybe_drag_obj)
03540               &&
03541               (*lia)->obj_which_emits_the_light == maybe_drag_obj->obj_and_pos.o )
03542         {
03543             on_lights.insert( *lia );
03544         }
03545         else
03546         {
03547             foreach(pl, players){
03548                 if ( (*pl)->loc == act_pl->loc)
03549                 {
03550                     foreach(ob, (*pl)->cache->sorted_items){
03551                         if (ob->o == (*lia)->obj_which_emits_the_light )
03552                         {
03553                             on_lights.insert( *lia );
03554                         }
03555                     }
03556                 }
03557             }
03558         }
03559     }
03560 }       
03561 
03562 
03563 
03564 void
03565 FACK::start()
03566 {
03567     // BEGIN decl
03568     pt<container_pick_result> itc;
03569     pt<PS_missing_two_items> missing_two_items;
03570     pt<PS_missing_one_item> missing_one_item;
03571     set<pt<light> > on_lights;
03572 
03573     bool ok;
03574     pt<sentence_with_location> sen;
03575     //seq_list<obj_and_pos>::const_iterator op;
03576     //SDL_Rect dest_rect;
03577     //bool blit_res;
03578     bool must_be_scaled;
03579     pt<still_situation_sitting> sitting;
03580     pt<AI_substate_speaking_while_sitting> sitting_talking;
03581     list<pt<layer_unlit_before_anim> >::const_iterator ql;
03582     list<pt<layer_unlit_after_anim> > unlit_layers_after_anim;
03583     list<pt<layer_unlit_after_anim> >::const_iterator l;
03584 
03585 
03586     pt<layer_lit> bg_layer_lit;
03587     list<pt<layer_lit> >::const_iterator xx;
03588     list<pt<anim_frame_and_pos> >::const_iterator xxc;
03589     list<pt<printable> > lit_layers_and_chars;
03590 
03591 
03592     update_AI_result update_AI_res;
03593     pt<anim_frame_and_pos> frame_and_pos;
03594     variant<no_sentence, sentence_with_location> maybe_sentence;
03595     sentence_with_location sentenc;
03596     float timer, dt;
03597     int timer_int, dt_int, previous_timer;
03598     list<SDL_Event> pending_events;
03599     list<SDL_Event>::const_iterator event;
03600     int_pair mouse_screen_coords;
03601     int_pair mouse_bg_coords;
03602 
03603     pt<obj_or_concept> other_item, item_to_disamb;
03604     pt<phys_obj_with_verbs> just_disambig, still_to_disamb;
03605     
03606     //int columns_count, item_wt;
03607 
03608     list<SDL_Surface*> inv_surfs;
03609     list<SDL_Surface*>::const_iterator sit;
03610     pt<vector<SDL_Surface *> >inv_surfs_2;
03611     pt<phys_obj> item_ph;
03612     variant<no_item, pt<obj_or_concept> > it, it2;
03613     pt<cfsurf> background;
03614     list<pt<layer_lit> > lit_layers;
03615     list<pt<anim_frame_and_pos> > characters;
03616     variant < no_route_found, pt<list<int_pair> > > maybe_route;
03617     pt<list<int_pair> > route2;
03618     pt<vector<int_pair> > route3;
03619     pt<PS_governed_by_AI> governed_by_AI;
03620     pt<anim_frame> cur_frame;
03621     list<int_pair>::const_iterator r;
03622     vector<int_pair>::const_iterator r3;    
03623     list<int_pair>::const_iterator r4; 
03624     pt<list<int_pair> > route4;
03625     vector<int_pair>::const_iterator r5; 
03626     pt<vector<int_pair> > route5;
03627     variant<walking_finished, int_pair> res;
03628     //vector<pt<obj> >::const_iterator ii;
03629     SDL_Rect cancel_rect;
03630     pt<PS_choosing_verb> choosing_verb;
03631 
03632 
03633     list<pt<dialog_choice>  > clicked_choices;
03634     list<pt<dialog_choice>  >::const_iterator cho;
03635 
03636     list<sentence_with_location> sentences_to_display;
03637     list<sentence_with_location>::const_iterator sent;
03638     //vector<pt<obj> >::const_iterator iin;
03639     speech_t speech;
03640     script_cmds_t commands;
03641 
03642 
03643     pt<game_state_normal_t> normal;
03644     pt<game_state_flashing_inv_t> flashing_inv;
03645 
03646     map<pt<PC>, pt<anim_frame> > cur_frame_of_player;
03647     pt<anim_frame> stil;
03648     pt<PS_still_and_parsing> still;
03649     special_button_pick_result special_but;
03650 
03651     SDL_Rect scrolling_rect;
03652     int_pair top_left, bottom_right;
03653 
03654 
03655     // END
03656 
03657 
03658     // BEGIN integrity
03659 //     foreach(ch, players){
03660 //         foreach(iin, (*ch)->inventory){
03661 //             assert(*iin);
03662 //         }
03663 //     }
03664     // END
03665 
03666 
03667 
03668     must_exit = false;
03669     previous_timer =  SDL_GetTicks();
03670 
03671     scrolling_rect = create_rect(0,0, 10,10);
03672 
03673     while( !must_exit) // main loop
03674     {
03675 
03676         // BEGIN calculate dt, the seconds passed since last frame
03677         timer_int =  SDL_GetTicks(); // milliseconds
03678         timer = float(timer_int); 
03679         dt_int = timer_int - previous_timer ; // milliseconds
03680         dt = float (dt_int / 1000.f); // dt is expressed in seconds
03681         previous_timer = timer_int;
03682         // END
03683 
03684 
03685 
03686 
03687         // BEGIN block 1: manage events
03688         if (!pt_cast(game_state, flashing_inv))
03689         {
03690             pending_events = get_sdl_events();
03691 
03692             SDL_GetMouseState(&mouse_screen_coords.x, &mouse_screen_coords.y);
03693             mouse_bg_coords = mouse_screen_coords + 
03694                 int_pair(scrolling_rect.x, scrolling_rect.y); 
03695 
03696             foreach(event, pending_events){
03697                 
03698                 gcn_input->pushInput(*event); // inform guichan
03699                 
03700                 if (event->type == SDL_MOUSEBUTTONUP)
03701                 {
03702                     // BEGIN decl
03703                     pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
03704                     pt<dragging_state_dragging_open_popup> drag_open_popup;
03705                     // END
03706                     mouse_screen_coords = int_pair(event->button.x, event->button.y);
03707                     mouse_bg_coords =  mouse_screen_coords +
03708                         int_pair(scrolling_rect.x, scrolling_rect.y);
03709 
03710                     if(pt_cast(act_pl->drag_st, maybe_drag_obj))
03711                     {
03712                         if(mouse_screen_coords == maybe_drag_obj->orig_mouse_pos)
03713                         {
03714                             maybe_drag_obj->orig_container->add_item_in_pos(
03715                                 maybe_drag_obj->obj_and_pos);
03716 
03717                             the_obj_was_clicked(maybe_drag_obj->obj_and_pos.o, mouse_screen_coords);
03718                         }
03719                         else
03720                         {
03721                             drop_item(maybe_drag_obj, mouse_screen_coords);
03722                         }
03723                         
03724 
03725                     }
03726                     else if(pt_cast(act_pl->drag_st, drag_open_popup))
03727                     {
03728                         drag_open_popup->pop->position_in_screen = mouse_screen_coords - 
03729                             drag_open_popup->offset_of_mouse_in_obj;
03730 
03731                         act_pl->open_popups.push_back(drag_open_popup->pop);
03732 
03733                     }
03734                     act_pl->drag_st = NEW(dragging_state_not_dragging());
03735                 }
03736                 else if ( event->type == SDL_MOUSEBUTTONDOWN ) 
03737                 {
03738                     mouse_screen_coords = int_pair(event->button.x, event->button.y);
03739                     mouse_bg_coords = mouse_screen_coords +
03740                         int_pair(scrolling_rect.x, scrolling_rect.y);
03741 
03742                     if (event->button.button == SDL_BUTTON_LEFT)
03743                     {
03744                         special_but = special_button_at_pos(mouse_screen_coords);
03745                         if(special_but == SBPR_CYCLE_PLAYER)
03746                         {
03747                             cycle_active_player();
03748                         }
03749                         else if (special_but == SBPR_STAY_FOLLOW)
03750                         {
03751                             quick_msg = NEW(quick_message("Not yet implemented."));
03752                         }
03753                         else if(special_but == SBPR_SAVE_LOAD)
03754                         {
03755                             if(gcn_options_window->isVisible())
03756                             {
03757                                 gcn_options_window->setVisible( false);
03758                                 gcn_save_window->setVisible( false);
03759                                 gcn_load_window->setVisible( false);
03760                             }
03761                             else
03762                             {
03763                                 gcn_options_window->setVisible( true);
03764                                 gcn_top_container->moveToTop(gcn_options_window.get());
03765                             }
03766                         }
03767                         else
03768                         {
03769                             if (pt_cast(act_pl->state, missing_one_item) 
03770                                 || pt_cast(act_pl->state, missing_two_items))
03771                             {
03772                                 // BEGIN decl
03773                                 pt<container_pick_result_obj_and_pos> obj_and_pos_clicked;
03774                                 pt<container_pick_result_obj> obj_clicked;
03775                                 pt<container_pick_result_container_drag_area> drag_cont;
03776                                 pt<container_pick_result_closing_area> close_cont;
03777                                 pt<container> cont;
03778                                 // END
03779 
03780                                 itc = item_in_popup_at_screen_pos(mouse_screen_coords);
03781 
03782 
03783                                 if(pt_cast(itc, obj_and_pos_clicked))
03784                                 {
03785                                     cont = dynamic_pointer_cast<container>(obj_and_pos_clicked->pop);
03786                                     assert(cont);
03787 
03788                                     act_pl->drag_st = 
03789                                         NEW(dragging_state_maybe_dragging_obj(
03790                                                 obj_and_pos_clicked->obj_and_pos, 
03791                                                 ( (mouse_screen_coords - obj_and_pos_clicked->pop->position_in_screen) - 
03792                                                   obj_and_pos_clicked->obj_and_pos.pos) /* offset_of_mouse_in_obj */,
03793                                                 cont,
03794                                                 mouse_screen_coords /* orig_mouse_pos */));
03795 
03796                                     cont->remove_item_not_recursively(obj_and_pos_clicked->obj_and_pos.o);
03797 
03798                                 }
03799                                 else if (pt_cast(itc, obj_clicked))
03800                                 {
03801                                     the_obj_was_clicked(obj_clicked->obj, mouse_screen_coords);
03802                                 }
03803                                 else if (pt_cast(itc, close_cont))
03804                                 {
03805                                     list_remove_one(act_pl->open_popups, close_cont->pop);
03806                                 }
03807                                 else if(pt_cast(itc, drag_cont))
03808                                 {
03809                                     act_pl->drag_st = 
03810                                         NEW(dragging_state_dragging_open_popup(
03811                                                 mouse_screen_coords - drag_cont->pop->position_in_screen /* offset_of_mouse_in_obj */,
03812                                                 drag_cont->pop));
03813 
03814                                     list_remove_one(act_pl->open_popups, drag_cont->pop);
03815                                 }
03816                                 else
03817                                 {
03818                                     // BEGIN decl
03819                                     pt<obj_or_concept> obj_or_conc;
03820                                     // END
03821 
03822                                     it2 = item_in_room_at_position( mouse_bg_coords,
03823                                                                     players,
03824                                                                     act_pl,
03825                                                                     cur_frame_of_player);
03826 
03827                                     if(var_cast(it2, obj_or_conc))
03828                                     {
03829                                         the_obj_was_clicked(obj_or_conc, mouse_screen_coords);
03830                                     }
03831                                     else
03832                                     {
03833                                         // he clicked in the void with the left mouse button
03834 
03835                                     }
03836                                 }
03837                             }
03838                             else if (pt_cast(act_pl->state, choosing_verb))
03839                             {
03840                                 if (point_in_rect( int_pair(event->button.x, 
03841                                                             event->button.y), 
03842                                                    choosing_verb->cancel_rect))
03843                                 {
03844                                     act_pl->state = NEW( PS_missing_two_items(
03845                                                              choosing_verb->anim,
03846                                                              choosing_verb->timer,
03847                                                              choosing_verb->cur_frame));
03848                                 }
03849                                 else
03850                                 {
03851                                     setof(  cho,
03852                                             choosing_verb->choices,
03853                                             point_in_rect( int_pair(event->button.x,
03854                                                                     event->button.y),
03855                                                            (*cho)->rect),
03856                                             clicked_choices);
03857 
03858                                     if(clicked_choices.size() >0)
03859                                     {
03860                                         // BEGIN decl
03861                                         pt<dialog_choice_verb_object> choice_verb_obj;
03862                                         // END
03863 
03864 
03865                                         if(pt_cast(clicked_choices.front(), choice_verb_obj))
03866                                         {
03867                                             // the user disambiguated the item
03868                                             execute_action_verb_object(
03869                                                 choice_verb_obj->v, 
03870                                                 choice_verb_obj->passive_obj /* no verb was chosen*/,
03871                                                 choice_verb_obj->obj_for_which_the_verb_was_chosen /* verb was chosen */); 
03872                                         }
03873                                         else
03874                                         {
03875                                             assert(dynamic_pointer_cast<dialog_choice_double_other>(clicked_choices.front()));
03876                                             execute_action_double_none_of_the_above(
03877                                                 choosing_verb->obj_one,
03878                                                 choosing_verb->obj_two);
03879                                         
03880                                         }
03881                                     }
03882                                 }
03883                             }
03884                             else if (pt_cast(act_pl->state, governed_by_AI))
03885                             {
03886                                 // ignore the click
03887                             }
03888                             else{
03889                                 assert(false); // unmanaged parser state
03890                             }            
03891                         }
03892                     }
03893                     else
03894                     {
03895                         // he did not press the left mouse button, but
03896                         // some other mouse button (right probably).
03897                         mouse_screen_coords = int_pair(event->button.x, event->button.y);
03898                         mouse_bg_coords = mouse_screen_coords +
03899                             int_pair(scrolling_rect.x, scrolling_rect.y);
03900 
03901                 
03902 
03903                         if(!pt_cast(act_pl->state, governed_by_AI))
03904                         {
03905                             // BEGIN move character to clicked point
03906                             if(is_walkable(*act_pl->loc->walking_map, 
03907                                            mouse_bg_coords.x,
03908                                            mouse_bg_coords.y))
03909                             {
03910                                 commands.clear();
03911                                 commands << NEW(scr_cmd_walk(mouse_bg_coords));
03912                                 execute_commands(act_pl, commands);
03913                             }
03914                             // END
03915                         }
03916                     }
03917                 }
03918 
03919             } // foreach
03920         }
03921 
03922         // END of block1: manage events.
03923 
03924 
03925 
03926 
03927 
03928 
03929 
03930 
03931 
03932 
03933         // BEGIN block 2: update the life of characters and layers
03934 
03935         gcn_gui->logic();
03936 
03937         recompute_on_lights(on_lights /* out */);
03938 
03939         characters.clear();
03940         sentences_to_display.clear();
03941         cur_frame_of_player.clear();
03942 
03943         if(  pt_cast(act_pl->state, missing_one_item) ||
03944              pt_cast(act_pl->state, missing_two_items ) ||
03945              pt_cast(act_pl->state, governed_by_AI))
03946         {
03947             // BEGIN decl
03948             list<pt<PC> >::const_iterator ch;
03949             // END
03950 
03951             foreach(ch, players){
03952 
03953                 if (pt_cast((*ch)->state,  still))
03954                 {
03955                     cur_frame_of_player[*ch] = update_still_anim(still, dt);
03956 
03957                     if (act_pl->loc == (*ch)->loc)
03958                     {
03959                         must_be_scaled =  !pt_cast((*ch)->still_situat, sitting );
03960 
03961                         characters.push_back(NEW( anim_frame_and_pos( 
03962                                                       map_get(cur_frame_of_player, *ch),
03963                                                       (*ch)->pos.x, 
03964                                                       (*ch)->pos.y,
03965                                                       must_be_scaled)));
03966                     }
03967                 }
03968                 else 
03969                 {
03970                     ok = pt_cast((*ch)->state, governed_by_AI);
03971                     assert(ok);
03972 
03973 
03974                     update_AI_res = update_AI_state( *ch, dt, 
03975                                                      int_pair(scrolling_rect.x,
03976                                                               scrolling_rect.y));
03977 
03978                     // BEGIN this is always necessary here, because
03979                     // the AI step could have relocated a torch!
03980                     recompute_on_lights(on_lights /* out*/);
03981                     // END
03982 
03983                     cur_frame_of_player[*ch] = update_AI_res.frame;
03984                     (*ch)->state = update_AI_res.new_player_state;
03985                     (*ch)->cur_dir = update_AI_res.dir;
03986                     (*ch)->pos = update_AI_res.pos;
03987                                     
03988                     if((*ch)->loc == act_pl->loc && update_AI_res.frame)
03989                     {
03990                         must_be_scaled =  !pt_cast((*ch)->still_situat, sitting );
03991 
03992                         characters.push_back(NEW(anim_frame_and_pos(
03993                                                      update_AI_res.frame,
03994                                                      update_AI_res.pos.x, 
03995                                                      update_AI_res.pos.y,
03996                                                      must_be_scaled)));
03997                             
03998                     }
03999 
04000                     if ((*ch)->loc == act_pl->loc && var_cast(update_AI_res.maybe_sentence, sentenc))
04001                     {
04002                         sentences_to_display.push_back(sentenc);
04003                     }
04004                 }
04005             }
04006 
04007 
04008             setof_(
04009                 (*ql)->get_cur_frame(dt),
04010                 ql,
04011                 act_pl->loc->sorted_unlit_layers_before_anim ,
04012                 (*ql)->visible,
04013                 unlit_layers_after_anim);
04014 
04015 
04016             scrolling_rect = find_scrolling_rect( int_pair(
04017                                                       unlit_layers_after_anim.front()->lit_versions.front().surf->apparent_wt,
04018                                                       unlit_layers_after_anim.front()->lit_versions.front().surf->apparent_ht));
04019 
04020 
04021             setof_ ( 
04022                 lit_layer_of_unlit_layer(**l, 
04023                                          on_lights,
04024                                          timer,
04025                                          scrolling_rect), 
04026                 l, 
04027                 unlit_layers_after_anim, 
04028                 true, 
04029                 lit_layers);
04030 
04031 
04032             bg_layer_lit = lit_layers.front(); 
04033             lit_layers.pop_front();
04034 
04035             lit_layers_and_chars.clear();
04036             foreach(xx, lit_layers){
04037                 lit_layers_and_chars.push_back(*xx);
04038             }
04039             foreach(xxc, characters){
04040                 lit_layers_and_chars.push_back(*xxc);
04041             }
04042 
04043             // BEGIN update quick message
04044             if(quick_msg)
04045             {
04046                 quick_msg->timer -= dt;
04047                 if(quick_msg->timer <0)
04048                 {
04049                     quick_msg = pt<quick_message>();
04050                 }
04051             }
04052             // END
04053 
04054 
04055             update_light_transitions(dt);
04056         }
04057 
04058         // END block 2: update the life.
04059 
04060 
04061 
04062 
04063 
04064 
04065 
04066 
04067 
04068         // BEGIN block 3: render (layers, chars, dialogs, drawers, etc).
04069         if (pt_cast(act_pl->state, missing_one_item) ||
04070             pt_cast(act_pl->state, missing_two_items ) ||
04071             pt_cast(act_pl->state, governed_by_AI))
04072         {
04073 
04074             // BEGIN decl
04075             pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
04076             pt<dragging_state_dragging_open_popup> drag_open_popup;
04077             list<pt<popup> >::const_iterator zo;
04078            
04079             // END
04080 
04081 
04082 
04083 
04084 
04085             render_layers_and_chars_in_correct_order(
04086                 lit_layers_and_chars, *bg_layer_lit->surf, screen, 
04087                 act_pl->loc->scaling_data,
04088                 scrolling_rect,
04089                 on_lights);
04090 
04091 
04092             // BEGIN render special buttons
04093             {
04094                 // BEGIN decl
04095                 SDL_Rect r;
04096                 bool ret;
04097                 // END
04098 
04099                 r.x = special_buttons_icon_pos.x;
04100                 r.y = special_buttons_icon_pos.y;
04101                 ret = SDL_BlitSurface(special_buttons_icon,
04102                                       NULL,
04103                                       screen, 
04104                                       &r);
04105                 assert (ret == 0);
04106             }
04107             // END
04108 
04109             render_command_bar( mouse_screen_coords,
04110                                 mouse_bg_coords,
04111                                 cur_frame_of_player); // before containers
04112 
04113             act_pl->cache->render(screen, game_state);
04114 
04115             foreach(zo, act_pl->open_popups){
04116                 (*zo)->render(screen, game_state);
04117             }
04118 
04119             if(pt_cast(act_pl->drag_st, maybe_drag_obj))
04120             {
04121                 // BEGIN decl
04122                 SDL_Rect r;
04123                 int_pair cur_obj_pos;
04124                 bool ret;
04125                 // END
04126 
04127                 cur_obj_pos = mouse_screen_coords - maybe_drag_obj->offset_of_mouse_in_obj;
04128                 r.x = cur_obj_pos.x;
04129                 r.y = cur_obj_pos.y;
04130                 ret = SDL_BlitSurface(maybe_drag_obj->obj_and_pos.o->get_inv_surf(),
04131                                       NULL,
04132                                       screen, 
04133                                       &r);
04134                 assert (ret == 0);
04135 
04136             }
04137             else if (pt_cast(act_pl->drag_st, drag_open_popup))
04138             {
04139                 drag_open_popup->pop->position_in_screen = 
04140                     mouse_screen_coords - drag_open_popup->offset_of_mouse_in_obj;
04141 
04142                 drag_open_popup->pop->render(screen, game_state);
04143             }
04144 
04145             foreach(sent, sentences_to_display){
04146 
04147                 draw_text_multiline_variable_ht(
04148                     sent->text, screen, sent->x_left, sent->y_top, 
04149                     sent->x_right, surf_of_letter, 
04150                     false /*actually draw*/,
04151                     sent->color);
04152             }
04153 
04154             // BEGIN render quick message
04155             if(quick_msg)
04156             {
04157                 print_x_centered_line_of_text(
04158                     quick_msg->text,
04159                     0, screen->w,
04160                     screen->h - act_pl->cache->picture->h - calc_command_bar_ht() * 2 /* y */,
04161                     surf_of_letter, screen, 
04162                     rgb(150, 150, 210));
04163             }
04164             // END
04165 
04166         }
04167         else if(pt_cast(act_pl->state, choosing_verb))
04168         { 
04169             // BEGIN decl
04170             list<pt<dialog_choice> > choices;
04171             // END
04172 
04173 
04174             draw_verb_dialog( choosing_verb->obj_one,
04175                               choosing_verb->obj_two,
04176                               surf_of_letter, 
04177                               screen, 
04178                               false /* actually draw */, 
04179                               mouse_screen_coords, 
04180                               cancel_rect /* out*/,
04181                               choices /* out*/);
04182         }
04183         gcn_gui->draw();
04184 
04185         // END block 3
04186 
04187 
04188 
04189 
04190 
04191 
04192 
04193 
04194 
04195 
04196 
04197 
04198         // BEGIN update game state
04199         if(pt_cast(game_state, flashing_inv))
04200         {
04201             flashing_inv->timer -= dt;
04202             if(flashing_inv->timer <= 0)
04203             {
04204                 game_state = NEW(game_state_normal_t());
04205             }
04206         }
04207         // END
04208 
04209 
04210 
04211 
04212 
04213         SDL_Flip(screen);
04214     }
04215 
04216     SDL_Quit();
04217 }
04218 
04219 FACK::FACK(int argc, char ** argv)
04220 {
04221 
04222     // BEGIN decl
04223     Uint32 videoflags;
04224     int button_ht;
04225     seq_list<pt<gcn::Widget> > options_widgets;
04226     seq_list<pt<gcn::Widget> >::const_iterator x, w;
04227     list<int> widths;
04228     int maxw;
04229     // END
04230 
04231     if((SDL_Init(SDL_INIT_VIDEO)==-1)) { 
04232         raise_exception("Could not initialize SDL." /*, SDL_GetError()*/);
04233     }
04234 
04235                                                                                               
04236     videoflags = choose_some_video_flags();        
04237         
04238     //BEGIN set video mode          
04239     if ( (argc > 1) &&  (strcmp(argv[1], "-full") == 0) ) {
04240         videoflags |= SDL_FULLSCREEN;}
04241 
04242     this->screen = SDL_SetVideoMode(320, 240, 32, videoflags);
04243     if (!screen) {
04244         raise_exception("Couldn't set 320x200x32 video mode. " /* SDL_GetError()*/);
04245     }
04246     //END 
04247 
04248 
04249     // BEGIN init guichan
04250 
04251     list_model = NEW(dir_watcher_list_model());
04252     gcn_gui = NEW(gcn::Gui());
04253     button_ht = 20;
04254 
04255     SDL_EnableUNICODE(1); // necessary for gcn::TextField to work!
04256 
04257     gcn_save_cont = NEW(gcn::Container());
04258     gcn_save_cont->setSize(300,150);
04259     gcn_save_cont->setOpaque(false);
04260 
04261     gcn_load_cont = NEW(gcn::Container());
04262     gcn_load_cont->setSize(screen->w - 20,
04263                            screen->h * 3 /4 );
04264     gcn_load_cont->setOpaque(false);
04265 
04266     gcn_options_cont = NEW(gcn::Container());
04267     gcn_options_cont->setOpaque(false);
04268 
04269     gcn_save_window = NEW(gcn::Window("Save"));
04270     gcn_save_window->setContent(gcn_save_cont.get());
04271     
04272 
04273 
04274     gcn_options_window = NEW(gcn::Window("Options"));
04275     gcn_options_window->setContent(gcn_options_cont.get());
04276     gcn_options_window->setPosition(100, 20);
04277 
04278 
04279     gcn_load_window = NEW(gcn::Window("Load"));
04280     gcn_load_window->setContent(gcn_load_cont.get());
04281     gcn_load_window->resizeToContent();
04282 
04283     gcn_top_container = NEW(gcn::Container());
04284     gcn_top_container->setDimension(gcn::Rectangle(0, 0, screen->w, screen->h));
04285     gcn_top_container->setOpaque(false);
04286     gcn_top_container->add(gcn_save_window.get());
04287     gcn_top_container->add(gcn_load_window.get());
04288     gcn_top_container->add(gcn_options_window.get());
04289 
04290 
04291     // save dialog
04292     
04293     gcn_save_text_field = NEW(gcn::TextField("quick save"));
04294     gcn_save_text_field->setSize(200, 20);
04295     gcn_save_cont->add(gcn_save_text_field.get());
04296 
04297     gcn_save_button = NEW(gcn::Button("Save"));
04298     gcn_save_button->setEventId("save_button_event");
04299     gcn_save_button->setPosition(0, button_ht );
04300     gcn_save_button->addActionListener(this);
04301     gcn_save_cont->add(gcn_save_button.get());
04302 
04303     gcn_cancel_save_button = NEW(gcn::Button("Cancel"));
04304     gcn_cancel_save_button->setEventId("cancel_save_button_event");
04305     gcn_cancel_save_button->setPosition(0, 2 * button_ht );
04306     gcn_cancel_save_button->addActionListener(this);
04307     gcn_save_cont->add(gcn_cancel_save_button.get());
04308 
04309 
04310     //  options dialog
04311     gcn_options_save_button = NEW(gcn::Button("Save"));
04312     gcn_options_save_button->setEventId("gcn_options_save_button");
04313     gcn_options_save_button->addActionListener(this);
04314     gcn_options_cont->add(gcn_options_save_button.get());
04315 
04316 
04317     gcn_options_load_button = NEW(gcn::Button("Load"));
04318     gcn_options_load_button->setPosition(0, button_ht );
04319     gcn_options_load_button->setEventId("gcn_options_load_button");
04320     gcn_options_load_button->addActionListener(this);
04321     gcn_options_cont->add(gcn_options_load_button.get());
04322 
04323     gcn_options_fullscreen_button = NEW(gcn::Button("Toggle full screen"));
04324     gcn_options_fullscreen_button->setPosition(0, 2 * button_ht );
04325     gcn_options_fullscreen_button->setEventId("gcn_options_fullscreen_button");
04326     gcn_options_fullscreen_button->addActionListener(this);
04327     gcn_options_cont->add(gcn_options_fullscreen_button.get());
04328 
04329     gcn_options_cancel_button = NEW(gcn::Button("Cancel"));
04330     gcn_options_cancel_button->setPosition(0, 3 * button_ht);
04331     gcn_options_cancel_button->setEventId("gcn_options_cancel_button");
04332     gcn_options_cancel_button->addActionListener(this);
04333     gcn_options_cont->add(gcn_options_cancel_button.get());
04334 
04335 
04336     gcn_options_quit_button = NEW(gcn::Button("Quit game"));
04337     gcn_options_quit_button->setPosition(0, 4 * button_ht);
04338     gcn_options_quit_button->setEventId("gcn_options_quit_button");
04339     gcn_options_quit_button->addActionListener(this);
04340     gcn_options_cont->add(gcn_options_quit_button.get());
04341 
04342 
04343     options_widgets =  seq_list<pt<gcn::Widget> > () << 
04344         gcn_options_quit_button <<
04345         gcn_options_cancel_button << gcn_options_fullscreen_button <<
04346         gcn_options_load_button << gcn_options_save_button;
04347 
04348     setof_ ( (*w)->getWidth(),
04349              w,
04350              options_widgets,
04351              true,
04352              widths);
04353 
04354     maxw = max( widths);
04355 
04356     gcn_options_cont->setSize(maxw, 120);
04357 
04358     foreach( x, options_widgets){
04359 
04360         (*x)->setWidth(maxw);
04361     }
04362 
04363     // load dialog
04364     gcn_load_listbox = NEW(gcn::ListBox( list_model.get() ));
04365 
04366     gcn_load_scroll_area = NEW(gcn::ScrollArea(gcn_load_listbox.get()));
04367     gcn_load_scroll_area->setSize(gcn_load_cont->getWidth(), 
04368                                   gcn_load_cont->getHeight() - 32);
04369     gcn_load_listbox->setSize(gcn_load_cont->getWidth() - gcn_load_scroll_area->getScrollbarWidth() -2, 
04370                               gcn_load_cont->getHeight() - 32);
04371 
04372 
04373     gcn_cancel_load_button = NEW(gcn::Button("Cancel"));
04374     gcn_cancel_load_button->setEventId("gcn_cancel_load_button");
04375     gcn_cancel_load_button->addActionListener(this);
04376     gcn_cancel_load_button->setPosition(0, gcn_load_cont->getHeight() - 30);
04377 
04378     gcn_load_cont->add(gcn_load_scroll_area.get());
04379     gcn_load_cont->add(gcn_cancel_load_button.get());
04380 
04381     // 
04382 
04383 
04384     gcn_load_window->resizeToContent();
04385     gcn_save_window->resizeToContent();
04386     gcn_options_window->resizeToContent();
04387 
04388     gcn_load_window->setVisible(false);
04389     gcn_save_window->setVisible(false);
04390     gcn_options_window->setVisible(false);
04391 
04392 
04393 
04394 
04395     gcn_graphics = NEW(gcn::SDLGraphics());
04396     gcn_graphics->setTarget(screen);
04397 
04398     gcn_image_loader = NEW(gcn::SDLImageLoader());
04399     gcn::Image::setImageLoader(gcn_image_loader.get()); 
04400 
04401     gcn_input = NEW(gcn::SDLInput());
04402 
04403     gcn_gui->setGraphics(gcn_graphics.get());
04404     gcn_gui->setInput(gcn_input.get());
04405     gcn_gui->setTop(gcn_top_container.get());
04406 
04407 
04408     gcn_font = NEW(gcn::ImageFont("data/fixedfont.bmp", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.;:"));
04409 
04410     gcn::Widget::setGlobalFont(gcn_font.get());
04411 
04412     // END
04413 
04414     this->game_state = NEW(game_state_normal_t());
04415 
04416     printf ("screen: pitch %d bytespp %d\n", screen->pitch, screen->format->BytesPerPixel);
04417 }
04418 
04419 
04420 
04421 SDL_Surface * can_appear_closed_in_inv_no::get_inv_surf()
04422 {
04423     assert(false);
04424 }
04425 
04426 SDL_Surface * can_appear_closed_in_inv_yes::get_inv_surf()
04427 {
04428     return inv_surf;
04429 }
04430 
04431 
04432 
04433 
04434 
04436 bool 
04437 anim_frame::point_in_surf(
04438     int_pair p /* point to be sampled (screen coords) */,
04439     int_pair pl /* position of the hot spot of the animation frame on the screen (screen coords) */,
04440     float scaling /* the scaling that will be applied to the frame */) const
04441 {
04442     // BEGIN decl
04443     int_pair r, l, j;
04444     rgbaf pix;
04445     // END
04446 
04447     r = p - pl;
04448 
04449     l = int_pair( int( float(r.x)/scaling ), int( float(r.y)/scaling)  );
04450 
04451     j = l + this->hot_spot;
04452     
04453 
04454     if ( 0 <= j.x && j.x < this->w 
04455          &&
04456          0 <= j.y && j.y < this->h)
04457     {
04458         pix = get_pixel( j.x, j.y);
04459 
04460         return (pix.a != 0.0f /* @@ dangerous to check for float equality? */ );
04461     }
04462     else
04463     {
04464         return false;
04465     }
04466 
04467 }
04468 
04469 
04470 void
04471 layer_lit::print_with_transparency(
04472     cfsurf & background,
04473     const room_scaling_data& d,
04474     set<pt<light> > active_lights)
04475 {
04476     surf->blit_with_src_alpha( background); 
04477 
04478 }
04479 
04480 void
04481 anim_frame_and_pos::print_with_transparency(
04482     cfsurf & background,
04483     const room_scaling_data& d,
04484     const set<pt<light> > active_lights)
04485 {
04486     // BEGIN decl
04487     float scal;
04488     float light_fact;
04489     float sum;
04490     set<pt<light> >::const_iterator l;
04491     map<pt<light>, float> normalized_weight_of_light;
04492     // END
04493 
04494     if (this->must_be_scaled)
04495     {
04496         scal = scaling_of_char( this->position_y, d);
04497     }
04498     else
04499     {
04500         scal = 1.0f;
04501     }
04502 
04503     // BEGIN find normalized_weight_of_light
04504     sum = 0.0f;
04505     foreach(l, active_lights){
04506         sum += (*l)->weight;
04507     }
04508 
04509     foreach(l, active_lights){
04510         normalized_weight_of_light[*l] = (*l)->weight / sum;
04511     }
04512     // END
04513 
04514     
04515     light_fact = 0.0f;
04516     foreach(l, active_lights){
04517         light_fact += 
04518             (*l)->pl_illum->get_illum_factor_at( this->position_x, this->position_y)
04519             *
04520             map_get( normalized_weight_of_light, *l);
04521     }
04522 
04523     blit_char(*this, scal, light_fact, background);
04524     
04525 }
04526 
04527 
04528 pt<layer_unlit_after_anim>
04529 layer_unlit_anim::get_cur_frame(float dt)
04530 {
04531     timer += dt;
04532     if (timer >= frame_change_interval)
04533     {
04534         timer -= frame_change_interval;
04535         cur_frame ++;
04536         if(cur_frame == anim.end())
04537         {
04538             cur_frame = anim.begin();
04539         }
04540 
04541     }
04542     return NEW(layer_unlit_after_anim(*cur_frame, y_walkbehind));
04543 
04544 }
04545 
04546 
04547 void
04548 FACK::define_dialog_aux(
04549     const dialog_t & dialog,
04550     pt<PC> first_player, 
04551     pt<PC> second_player, 
04552     script_cmds_t & steps_first,
04553     script_cmds_t & steps_second) const
04554 {
04555     // BEGIN decl
04556     dialog_t::const_iterator i;
04557     pt<PC> who_speaks_next;
04558     // END
04559 
04560     who_speaks_next = first_player;
04561     foreach(i, dialog){
04562         if(who_speaks_next == first_player)
04563         {
04564             steps_first << NEW(scr_cmd_speak( *i, close_any_open_container));
04565             steps_second << NEW(scr_cmd_wait_for_person_to_stop_talking(first_player));
04566 
04567             who_speaks_next = second_player;
04568         }
04569         else
04570         {
04571             steps_second << NEW(scr_cmd_speak(*i, close_any_open_container ));
04572             steps_first << NEW(scr_cmd_wait_for_person_to_stop_talking(second_player));
04573 
04574             who_speaks_next = first_player;
04575 
04576         }
04577     }
04578 }
04579 
04580 
04581 
04582 
04583 pt<animation>
04584 anim_right_left::get_anim(horizontal_dir dir) const
04585 {
04586     if (dir == hd_right)
04587     {
04588         return this->right;
04589     }
04590     else
04591     {
04592         return this->left;
04593     }
04594 
04595 }
04596 
04597 
04598 
04599 
04600 
04601 
04602 void
04603 write_string(
04604     ostream& o, string s)
04605 {
04606 
04607      o << s.length() << ":" << s;
04608 }
04609 
04610 
04611 string 
04612 read_string(
04613     istream & i)
04614 {
04615     // BEGIN decl
04616     size_t len;
04617     string ret;
04618     int c;
04619     char colon;
04620     char ch;
04621     // END
04622 
04623 
04624     i >> len;
04625     i >> colon;
04626     assert(colon == ':');
04627 
04628     ret = "";
04629     for (c = 0; c < len; c++)
04630     {
04631         i >> ch;
04632         ret += ch;
04633     }
04634 
04635     return ret;
04636 
04637 }
04638 
04639 
04640 
04641 // void
04642 // FACK::save_game()
04643 // {
04644 //     // BEGIN decl
04645 //     long version;
04646 //     ofstream file;
04647 //     seq_list<pt<PC> >::const_iterator p;
04648 //     // END
04649 
04650 //     version = 1;
04651 
04652 //     file.open("savegame.binary");
04653 
04654 
04655 
04656 //     file <<  version << " ";
04657 
04658 
04659 //     this->game_state->serialize(file);
04660 
04661 
04662 //     file << " ";
04663 //     write_string(file, act_pl->get_persistent_id());
04664 //     file << " ";
04665     
04666 //     foreach(p, players){
04667 //      (*p)->save(file);
04668 
04669 //     }
04670 
04671 
04672 //     this->save(file /*mod*/);
04673 // }
04674 
04675 
04676 // void
04677 // FACK::load_game(
04678 //     const list<pt<obj> > & objects,
04679 //     const list<pt<location> > & locations,
04680 //     const list<pt<PC> > & players)
04681 // {
04682 //     // BEGIN decl
04683 //     ifstream file;
04684 //     long version;
04685 //     seq_list<pt<PC> >::const_iterator p;
04686 //     seq_list<pt<PC> > pp;
04687 //     string pl_pid;
04688 //     // END
04689     
04690 //     file.open("savegame.binary");
04691 //     file >> version;
04692 //     assert(version == 1);
04693 
04694 //     game_state = game_state_t::deserialize(file, objects);
04695     
04696 
04697 //     pl_pid = read_string(file);
04698 
04699 //     setof(p, players, (*p)->get_persistent_id() == pl_pid, pp);
04700 //     act_pl = pp.front();
04701 
04702 //     foreach(p, players){
04703 //      (*p)->load(file, objects, locations);
04704 //     }
04705 
04706 
04707 //     this->load(file);
04708 
04709 // }
04710 // void
04711 // PC::save(
04712 //     ofstream& file)
04713 // {
04714 //     // BEGIN decl
04715 //     vector<pt<obj> >::const_iterator i;
04716 //     // END
04717 
04718 //     file << " " << pos.x << " " << pos.y << " " << inv_scrolling << " ";
04719 
04720 
04721 //     write_string(file, loc->get_persistent_id());
04722 
04723 //     file <<  /*" " << cur_dir << */
04724 //      " " << inventory.size();
04725 
04726 //     foreach(i, inventory){
04727         
04728 //      file << " ";
04729 //      write_string(file, (*i)->get_persistent_id());
04730 //     }
04731 
04732 // }
04733 
04734 // void
04735 // PC::load(
04736 //     ifstream& file,
04737 //     const list<pt<obj> >& objects,
04738 //     const list<pt<location> > & locations)
04739 // {
04740 //     // BEGIN decl
04741 //     int i_size, i;
04742 //     string loc_id, item_id;
04743 //     list<pt<location> > xx;
04744 //     list<pt<location> >::const_iterator l;
04745 //     list<pt<obj> > ss;
04746 //     list<pt<obj> >::const_iterator x;
04747 //     // END
04748 
04749 //     inventory.clear();
04750 
04751 //     file >> pos.x >> pos.y >>  inv_scrolling ;
04752 
04753 //     loc_id = read_string(file);
04754 //     setof(l, locations, (*l)->get_persistent_id() == loc_id, xx);
04755 //     this->loc = xx.front();
04756 
04757 
04758 
04759 //     //file >> c >> cur_dir;
04760 
04761 
04762 //     file >> i_size;
04763 
04764 //     for(i = 0; i< i_size; i++)
04765 //     {
04766 //      item_id = read_string(file);
04767 //      setof(x, objects, (*x)->get_persistent_id() == item_id, ss);
04768 //      inventory.push_back(ss.front());
04769 //     }
04770 
04771 // }
04772 
04773         
04774 // void 
04775 // game_state_flashing_inv_t::serialize(
04776 //     ostream& file)const 
04777 // {
04778 //     write_string(file, "flashing");
04779 
04780 //     file << " " << item->get_persistent_id() << " " << timer << " " << paused;
04781 
04782 // }
04783 // void 
04784 // game_state_flashing_inv_t::deserialize_once_subtype_known(
04785 //     istream& file,
04786 //     const list<pt<obj> > & objects) 
04787 // {
04788 //     // BEGIN decl
04789 
04790 //     string loc_id, item_id;
04791 //     list<pt<location> > xx;
04792 //     list<pt<location> >::const_iterator l;
04793 //     list<pt<obj> > ss;
04794 //     list<pt<obj> >::const_iterator x;
04795 //     // END
04796 
04797 //     // BEGIN init item
04798 //     setof(x, objects, (*x)->get_persistent_id() == read_string(file), ss);
04799 //     this->item = ss.front();
04800 
04801 //     // END
04802 
04803 
04804 //     file >> timer >> paused;
04805 // }
04806         
04807 // void 
04808 // game_state_normal_t::serialize(
04809 //     ostream& file)const 
04810 // {
04811 //     write_string(file, "normal");
04812 
04813 //     file << " " <<paused;
04814 
04815 // }
04816 // void 
04817 // game_state_normal_t::deserialize_once_subtype_known(
04818 //     istream& file,
04819 //     const list<pt<obj> > & objects) 
04820 // {
04821 
04822 //     file >> paused;
04823 // }
04824 
04825 
04826 // pt<game_state_t>
04827 // game_state_t::deserialize(
04828 //     istream& file,
04829 //     const list<pt<obj> > & objs)
04830 // {
04831 //     // BEGIN decl
04832 //     pt<game_state_t> ret;
04833 //     string id;
04834 //     // END
04835 
04836 //     id = read_string(file);
04837 
04838 //     if(id == "flashing")
04839 //     {
04840 //      ret = NEW(game_state_flashing_inv_t());
04841 //     }
04842 //     else
04843 //     {
04844 //      assert(id == "normal");
04845 //      ret = NEW(game_state_normal_t());
04846 //     }
04847 //     ret->deserialize_once_subtype_known(file, objs);
04848 //     return ret;
04849 
04850 // }
04851 
04852 
04853 
04854 
04855 int_pair
04856 int_pair::operator-(
04857     const int_pair& p) const
04858 {
04859     return int_pair(x - p.x, y-p.y);
04860 }
04861 int_pair
04862 int_pair::operator+(
04863     const int_pair& p) const
04864 {
04865     return int_pair(x + p.x, y + p.y);
04866 }
04867 
04868 
04869 // SDL_Rect
04870 // FACK::calc_inv_rect() const
04871 // {
04872 //     SDL_Rect r;
04873 
04874 //     r.w = inv_icon->w;
04875 //     r.h = inv_icon->h;
04876 
04877 //     r.x = 0;
04878 //     r.y = screen->h - 2* width_of_scroll_arrow - 2 - map_get(surf_of_letter, 'a')->h - inv_icon->h;
04879 
04880 //     return r;
04881 
04882 // }
04883 
04884     
04885 template<class T>
04886 void
04887 vector2<T>::fill_with(
04888     const T& val)
04889 {
04890     // BEGIN decl.
04891     int i;
04892     // END
04893     for( i= 0; i < w * h ; i++)
04894     {
04895         v[i] = val;
04896     }
04897 }
04898 
04899 
04900 void
04901 container::add_item( 
04902     const pt<obj_or_concept> i)
04903 {
04904     sorted_items.push_back(pos_and<pt<obj_or_concept> >(
04905                                i, int_pair(drop_in_area.x + drop_in_area.w/3,
04906                                            drop_in_area.y + drop_in_area.h /3)));
04907 }
04908 
04909 
04910 void
04911 container::remove_item_not_recursively(
04912     const pt<obj_or_concept> item)
04913 {
04914     // BEGIN decl
04915     list<pos_and<pt<obj_or_concept> > >::iterator i;
04916     // END
04917 
04918     foreach(i, sorted_items)
04919     {
04920         if (i->o == item) 
04921         {
04922             i = sorted_items.erase(i);
04923             return;
04924         }
04925     }
04926 
04927     assert(false);
04928 }
04929 
04930 
04931 bool
04932 container::remove_item_aux(
04933     const pt<obj_or_concept> item)
04934 {
04935     // BEGIN decl
04936     list<pos_and<pt<obj_or_concept> > >::iterator i;
04937     // END
04938 
04939     foreach(i, sorted_items)
04940     {
04941         if (i->o == item) 
04942         {
04943             i = sorted_items.erase(i);
04944             return true;
04945         }
04946     }
04947     return false;
04948 
04949 }
04950 
04951 bool
04952 container::remove_item_rec_aux(
04953     const pt<obj_or_concept> item)
04954 {
04955     // BEGIN decl
04956     list<pos_and<pt<obj_or_concept> > >::const_iterator i;
04957     pt<container> container;
04958     bool ret, found;
04959     // END
04960 
04961     ret =  remove_item_aux(item);
04962 
04963     if(ret)
04964     {
04965         return true;
04966     }
04967     else
04968     {
04969         found = false;
04970         foreach(i, sorted_items){
04971             if (pt_cast(i->o, container))
04972             {
04973                 ret = container->remove_item_rec_aux(item);
04974 
04975                 if(ret)
04976                     found = true;
04977             }
04978         }
04979         return found;
04980     }
04981 
04982 }
04983 
04984 
04985 void
04986 container::remove_item_recursively(
04987     const pt<obj_or_concept> item)
04988 {
04989     bool found;
04990 
04991     found = remove_item_rec_aux(item);
04992 
04993     if(!found)
04994         assert(false);
04995 
04996 }
04997 void
04998 container::add_item_in_pos(
04999     pos_and<pt<obj_or_concept> > obj_and_pos)
05000 {
05001     sorted_items.push_back(obj_and_pos);
05002 }
05003 
05004 bool
05005 FACK::contains_recursively(
05006     pt<container> cont,
05007     pt<obj_or_concept> o,
05008     pt<container> & real_cont,
05009     int_pair & pos )
05010 {
05011     // BEGIN decl
05012     list<pos_and<pt<obj_or_concept> > >::const_iterator i;
05013     pt<container> container, con;
05014     int_pair po;
05015     // END
05016 
05017     if(contains_not_recursively(cont, o, po /* out */))
05018     {
05019         real_cont = cont;
05020         pos = po;
05021         return true;
05022     }
05023     else
05024     {
05025         foreach(i, cont->sorted_items){
05026             if (pt_cast(i->o, container))
05027             {
05028                 if(contains_recursively(container, 
05029                                         o,
05030                                         con /* out */, 
05031                                         po /* out */))
05032                 {
05033                     real_cont = con;
05034                     pos = po;
05035                     return true;
05036                 }
05037             }
05038         }
05039 
05040 //      real_cont = pt<container>(0);
05041 //      pos = int_pair(-1, -1);
05042         return false;
05043     }
05044 }
05045 
05046 bool
05047 FACK::contains_not_recursively(
05048     pt<container> cont,
05049     pt<obj_or_concept> o,
05050     int_pair & pos) 
05051 {
05052     // BEGIN decl
05053     list<pos_and<pt<obj_or_concept> > >::const_iterator i;
05054     // END
05055 
05056     foreach(i, cont->sorted_items){
05057         if (i->o == o )
05058         {
05059             pos = i->pos;
05060             return true;
05061         }
05062     }
05063 
05064     pos = int_pair(-1, -1);
05065     return false;
05066 }
05067 
05068 
05069 bool
05070 container::can_contain_this_obj(pt<obj_or_concept> o)const
05071 {
05072     // BEGIN decl
05073     pt<phys_obj> phys;
05074     pt<concept> conc;
05075     pt<container> cont;
05076     pt<zoomable> zoomab;
05077     // END
05078 
05079     if(type == CAN_CONTAIN_ANYTHING)
05080         return true;
05081     else if (pt_cast(o, zoomab))
05082     {
05083         return true;
05084     }
05085     else
05086     {
05087         if(pt_cast(o, cont))
05088         {
05089             return cont->type == type;
05090         }
05091         else
05092         {
05093             return ( (type == PHYS_OBJECTS && pt_cast(o, phys))
05094                      ||
05095                      (type == CONCEPTS && pt_cast(o, conc)));
05096         }
05097     }
05098 
05099 }
05100 
05101 bool
05102 container::can_be_moved_across_containers()const
05103 {
05104     return pick_up_info->can_be_moved_across_containers();
05105 }
05106 bool
05107 phys_obj::can_be_moved_across_containers()const
05108 {
05109     return pick_up_info->can_be_moved_across_containers();
05110 }
05111 
05112 SDL_Rect
05113 create_rect(
05114     int x1, int y1, int x2, int y2)
05115 {
05116     // BEGIN decl
05117     SDL_Rect r;
05118     // END
05119 
05120     // BEGIN precond
05121     assert(x2 >= x1);
05122     assert(y2 >= y1);
05123     // END
05124 
05125     r.x = x1; r.y = y1;
05126     r.w = x2 - x1;
05127     r.h = y2 - y1;
05128     return r;
05129 }
05130 
05131 special_button_pick_result
05132 FACK::special_button_at_pos(
05133     int_pair pos) const
05134 {
05135     if(point_in_rect(pos, this->zone_save_load_game))
05136     {
05137         return SBPR_SAVE_LOAD;
05138     }
05139     else if (point_in_rect(pos, this->zone_cycle_active_player))
05140     {
05141         return SBPR_CYCLE_PLAYER;
05142     }
05143     else if (point_in_rect(pos, this->zone_toggle_stay_follow))
05144     {
05145         return SBPR_STAY_FOLLOW;
05146     }
05147     else
05148     {
05149         return SBPR_NOTHING;
05150     }
05151 }
05152 
05153 bool
05154 zoomable_zone::point_in_zone(int_pair point) const
05155 {
05156     return point_in_rect(point, rect); 
05157 
05158 }
05159 
05160 
05161 void
05162 FACK::update_light_transitions( float dt )
05163 {
05164     // BEGIN decl
05165     list<pt<transition_of_fixed_light> > ::iterator t;
05166     pt<transition_of_fixed_light> tr;
05167     float m;
05168     set<pt<location> >::iterator lo;
05169     // END
05170 
05171 
05172     for(t = transitions_of_fixed_light.begin();
05173         t != transitions_of_fixed_light.end();
05174         t++)
05175     {
05176         tr = *t;
05177         assert( tr->cur_timer < tr->end_timer);
05178 
05179         tr->cur_timer += dt;
05180 
05181         if (tr->cur_timer >= tr->end_timer)
05182         {
05183             tr->ligh->weight = tr->end_intensity;
05184 
05185             t = transitions_of_fixed_light.erase(t);
05186 
05187             if(tr->switch_off_light_at_the_end)
05188             {
05189                 foreach( lo, locations){
05190                     if(in( tr->ligh, (*lo)->active_lights))
05191                     {
05192                         (*lo)->active_lights.erase(tr->ligh);
05193                         cout << "Erased light from loc" << endl;
05194                     }
05195                 }
05196             }
05197         }
05198         else
05199         {
05200             m = (tr->end_intensity - tr->start_intensity)/ tr->end_timer;
05201 
05202             tr->ligh->weight = 
05203                 tr->start_intensity + m * tr->cur_timer;
05204 
05205         }
05206 
05207     }
05208 }
05209 
05210 
05211 pt<circle_t>
05212 FACK::circle_of_light(pt<light> l) const
05213 {
05214     // BEGIN decl
05215     list<pt<PC> >::const_iterator p;
05216     pt<PC> pl;
05217     int_pair center, pos;
05218     pt<light_across_loc> torch;
05219     pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
05220     // END
05221 
05222     if(!pt_cast(l, torch))
05223     {
05224         return pt<circle_t>();
05225     }
05226     else
05227     {
05228         pl = pt<PC>();
05229 
05230         foreach(p, players){
05231 
05232             if( contains_not_recursively( (*p)->cache,
05233                                           torch->obj_which_emits_the_light,
05234                                           pos /*out*/))
05235             {
05236                 pl = *p;
05237                 break;
05238             }
05239             else if (pt_cast( (*p)->drag_st, maybe_drag_obj))
05240             {
05241                 if (maybe_drag_obj->obj_and_pos.o ==  torch->obj_which_emits_the_light )
05242                 {
05243                     pl = *p;
05244                     break;
05245                 }
05246             }
05247         }
05248         assert(pl);
05249 
05250         center = pl->pos; 
05251 
05252         return NEW(circle_t( torch->light_radius, center));
05253     }
05254 }
05255 
05256 
05257 void 
05258 FACK::action(const string& eventId)
05259 {
05260 
05261     if (eventId == "cancel_save_button_event")
05262     {
05263         gcn_save_window->setVisible(false);
05264     }
05265     else if (eventId == "gcn_options_quit_button")
05266     {
05267         must_exit = true;
05268     }
05269     else if (eventId == "gcn_options_save_button")
05270     {
05271         gcn_save_window->setVisible(true);
05272         gcn_top_container->moveToTop(gcn_save_window.get());
05273         gcn_options_window->setVisible(false);
05274     }
05275     else if (eventId == "gcn_options_load_button")
05276     {
05277         list_model->rescan_dir();
05278         gcn_load_window->setVisible(true);
05279         gcn_top_container->moveToTop(gcn_load_window.get());
05280         gcn_options_window->setVisible(false);
05281     }
05282     else if (eventId == "gcn_options_fullscreen_button")
05283     {
05284         SDL_WM_ToggleFullScreen(screen);
05285 
05286     }
05287     else if (eventId == "gcn_cancel_load_button")
05288     {
05289         gcn_load_window->setVisible(false);
05290     }
05291     else if (eventId == "gcn_options_cancel_button")
05292     {
05293         gcn_options_window->setVisible(false);
05294     }
05295     
05296     
05297 
05298 }
05299 
05300 
05301 dir_watcher_list_model::dir_watcher_list_model()
05302 {
05303     rescan_dir();
05304 }
05305 
05306 int
05307 dir_watcher_list_model::getNumberOfElements()
05308 {
05309     return strings.size();
05310 }
05311 
05312 string
05313 dir_watcher_list_model::getElementAt(int i)
05314 {
05315     return strings[i];
05316 }
05317 
05318 
05319 void
05320 dir_watcher_list_model::rescan_dir()
05321 {
05322     // BEGIN decl
05323     boost::filesystem::directory_iterator itr;
05324     string::size_type q;
05325     // END
05326 
05327     strings.clear();
05328 
05329     boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end
05330     
05331     for ( itr = boost::filesystem::directory_iterator( boost::filesystem::current_path() );
05332           itr != end_itr;
05333           ++itr )
05334     {
05335         if (boost::filesystem::is_directory(*itr))
05336         {
05337 
05338         }
05339         else
05340         {
05341             q = itr->leaf().find(".savegame");
05342             if (q != string::npos)
05343             {
05344                 strings.push_back(itr->leaf());
05345             }
05346         }
05347     }
05348 }

Generated on Wed May 25 15:36:06 2005 for FACK by  doxygen 1.4.0