OSDN Git Service

日本語版
[nazghul-jp/nazghul-jp.git] / src / player.cpp
1 //
2 // nazghul - an old-school RPG engine
3 // Copyright (C) 2002, 2003 Gordon McNutt
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 2 of the License, or (at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13 // more details.
14 //
15 // You should have received a copy of the GNU General Public License along with
16 // this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
17 // Suite 330, Boston, MA 02111-1307 USA
18 //
19 // Gordon McNutt
20 // gmcnutt@users.sourceforge.net
21 //
22 #include "player.h"
23 #include "object.h"
24 #include "status.h"
25 #include "console.h"
26 #include "place.h"
27 #include "Party.h"
28 #include "screen.h"
29 #include "sound.h"
30 #include "terrain.h"
31 #include "map.h"
32 #include "foogod.h"
33 #include "combat.h"
34 #include "wind.h"
35 #include "dup_constants.h"
36 #include "cmdwin.h"
37 #include "vehicle.h"
38 #include "sprite.h"
39 #include "cmd.h"             // for ui_get_direction()
40 #include "Field.h"
41 #include "event.h"
42 #include "formation.h"
43 #include "ctrl.h"
44 #include "session.h"
45 #include "log.h"
46 #include "factions.h"
47 #include "gob.h"
48
49 #include <unistd.h>
50 #include <math.h>
51
52 #define CAMPING_TIME_ACCELERATION (TURNS_PER_HOUR)
53
54
55 #define DIRLOC(dir,place,coord) { \
56     if ((dir) < 0) \
57         (coord) = place_w((place)) - 1; \
58     else if (! (dir)) \
59         (coord) = place_w((place)) / 2; \
60     else \
61         (coord) = 0; \
62 }
63
64 extern void play_update_place_viewer(void);     /* hack */
65
66
67 static bool apply_damage(class Character * pm, void *amount)
68 {
69         pm->damage(*((int *)amount));
70         return false;
71 }
72
73 void PlayerParty::damage(int amount)
74 {
75         /* First apply damage to the vehicle. If the vehicle is destroyed then
76            destroy the party, too. */
77         if (vehicle && vehicle->isVulnerable()) {
78
79                 // Subtle: save a pointer to the vehicle. If vehicle->damage()
80                 // actually destroys the vehicle, then in a roundabout way by
81                 // the time that call returns we will have disembarked (meaning
82                 // our usual vehicle pointrer will be NULL). But we still bear
83                 // responsibility hear for destroying the vehicle. Messy, but
84                 // there you go. It works and I don't care to fool with it.
85                 class Vehicle *vehptr = vehicle;
86
87                 obj_inc_ref(vehicle);
88                 vehicle->damage(amount);
89                 mapFlash(0);
90                 foogodRepaint();
91
92                 /* If the vehicle is destroyed then we are dead. */
93                 if (vehptr->isDestroyed()) {
94                         vehicle = NULL;   
95                 }
96
97                 obj_dec_ref(vehptr);
98
99                 return;
100         }
101
102         /* Apply damage to all party members. If they all die then the party is
103            destroyed, too. */
104         forEachMember(apply_damage, &amount);
105 }
106
107 static bool pc_get_first_living(class Character * pm, void *data)
108 {
109         class Character **pc = (class Character**)data;
110         if (!pm->isDead()) {
111                 *pc = pm;
112                 return true;
113         }
114         return false;
115 }
116
117 static bool pc_check_if_alive(class Character * pm, void *data)
118 {
119         int *count = (int *) data;
120         if (!pm->isDead()) {
121                 (*count)++;
122                 return false;
123         }
124         return false;
125 }
126
127 static bool pc_check_if_not_immobilized(class Character * pm, void *data)
128 {
129         int *count = (int *) data;
130         if (!pm->isAsleep()) {
131                 (*count)++;
132                 return false;
133         }
134         return false;
135 }
136
137 static bool pc_eat_food(class Character * pm, void *data)
138 {
139         if (pm->isDead()) {
140                 return false;
141         }
142
143         if (player_party->food) {
144                 player_party->food--;
145                 return false;
146         }
147
148         log_msg("µ²¤¨»à¤Ë¤·¤½¤¦¤À¡ª");
149
150         /* Partial fix for SF BUG [ 1526910 ] "starvation is lame". Instead of
151          * a fixed amount of damage, make damage proportional to existing
152          * health. The player can starve for a while before dying, but the loss
153          * of HP is a serious threat now even at high levels. */
154         int damage = max(pm->getHp()/2, 1);
155         apply_damage(pm, &damage);
156         return false;
157 }
158
159 void PlayerParty::changePlaceHook()
160 {
161         mapSetPlace(place);
162         Place = place;
163         place_enter(place);
164         log_banner("%s¤Ë­¤òƧ¤ßÆþ¤ì¤¿", Place->name);
165         
166         // --------------------------------------------------------------------
167         // If the party is relocating to a non-wilderness place then I have to
168         // break it out.
169         // --------------------------------------------------------------------
170         
171         if (! place_is_wilderness(place)) {
172                 distributeMembers(place, x, y, dx, dy);
173                 return;
174         } else {
175                 foogod_set_title("¹ÓÌî¤Îι");
176                 foogodRepaint();
177         }
178 }
179
180 enum move_result PlayerParty::check_move_to(struct move_info *info)
181 {
182         class Party *npc_party;
183
184         // null place?
185         if (!info->place)
186                 return move_null_place;
187
188         info->x = place_wrap_x(info->place, info->x);
189         info->y = place_wrap_y(info->place, info->y);
190
191         // off-map?
192         if (place_off_map(info->place, info->x, info->y)) {
193                 return move_off_map;
194         }
195         // occupied (this handles occupied vehicles, too)
196         if ((npc_party = place_get_Party(info->place, info->x, info->y))) {
197                 if (are_hostile(this, npc_party)) {
198                         if (info->place->wilderness) {
199                                 info->npc_party = npc_party;
200                         }
201                         return move_enter_combat;
202                 }
203                 return move_occupied;
204         }
205         // another vehicle?
206         if (vehicle && place_get_vehicle(info->place, info->x, info->y))
207                 return move_occupied;
208
209         // pass subp vehi
210         // *    t    t    exit vehicle
211         // t    f    *    ok
212         // f    f    *    impassable
213
214         info->subplace = place_get_subplace(info->place, info->x, info->y);
215         if (info->subplace) {
216                 if (vehicle)
217                         return move_not_in_vehicle;
218                 return move_enter_subplace;
219         }
220
221         // passable? I moved this check to be before a test for portals. A
222         // portal is accessible iff the player can move across the terrain it
223         // is placed on. The "ladder in the lake to the ladder on land" test
224         // case just plain looks counterintuitive without it.
225         if (!place_move_is_passable(info->place, info->x - info->dx, info->y-info->dy, info->x, info->y, this, 
226                                PFLAG_MOVEATTEMPT))
227                 return move_impassable;
228
229         return move_ok;
230 }
231
232 bool PlayerParty::turn_vehicle(void)
233 {
234         int cost = 0;
235
236         // Three possible outcomes:
237         // 
238         // 1. We do NOT turn any vehicle, therefore we want to continue
239         // processing the move() command which calls us and we do NOT want to
240         // consume any turns (e.g., no vehicle, or horse turning north/south).
241         // 
242         // 2. We DO turn a vehicle, but it does not cost us anything (e.g.,
243         // horse turning east/west).
244         // 
245         // 3. We do turn a vehicle and it cost us a turn (e.g., ship).
246
247         if (!vehicle || !vehicle->turn(dx, dy, &cost) || !vehicle->mustTurn())
248                 return false;
249
250         return true;
251 }
252
253
254 /* Note it is not safe to modify the member list within the block of the below
255  * 'iterator'  */
256 #define FOR_EACH_MEMBER(e,c) \
257         for ((e) = node_next(&members), (c) = (class Character *)(e)->ptr; \
258            (e) != &members; \
259            (e) = node_next(e), (c) = (class Character *)(e)->ptr)
260
261 #define FOR_EACH_REVERSE_MEMBER(e,c) \
262         for ((e) = node_prev(&members), (c) = (class Character *)(e)->ptr; \
263            (e) != &members; \
264            (e) = node_prev(e), (c) = (class Character *)(e)->ptr)
265
266
267 void PlayerParty::distributeMembers(struct place *new_place, int new_x, 
268                                      int new_y, int new_dx, int new_dy)
269 {
270         // --------------------------------------------------------------------
271         // Remove the player party from the current place and remove its view
272         // from the map viewer's consideration (instead we'll use the character
273         // views, which are added as each character is placed on the map
274         // below).
275         // --------------------------------------------------------------------
276
277         remove();
278
279         // --------------------------------------------------------------------
280         // Switch the current place to the portal destination place.
281         // --------------------------------------------------------------------
282
283         Place = new_place;
284
285         // --------------------------------------------------------------------
286         // Set the new destination place to be the subject of the map
287         // viewer. Center the camera on the portal destination.
288         // --------------------------------------------------------------------
289
290         mapSetPlace(new_place);
291         mapCenterCamera(new_x, new_y);
292         mapSetDirty();
293
294         // --------------------------------------------------------------------
295         // Distribute all the party members centered on the portal destination
296         // point. I assume this always succeeds, which means I'm relying on map
297         // editors to be nice and make nice, clear areas around their portal
298         // entrances.
299         //
300         // For now, I'll reuse the existing combat placement algorithm. Compare
301         // the code below with position_player_party() in combat.c:
302         // --------------------------------------------------------------------
303
304         struct node *entry;
305         class Character *member;
306
307         FOR_EACH_REVERSE_MEMBER(entry, member) {
308                 if (!member->isDead()) {
309
310                         int flags = 0;
311
312                         if (member->putOnMap(new_place, new_x, new_y, 
313                                              2 * size, 0))
314                                 continue;
315
316                         // Try again, ignoring other objects.
317                         flags |= PFLAG_IGNOREMECHS;
318                         flags |= PFLAG_IGNOREBEINGS;
319                         if (member->putOnMap(new_place, new_x, new_y, 
320                                              2 * size, flags))
321                                 continue;
322
323                         // Try again, ignoring hazards.
324                         flags |= PFLAG_IGNOREHAZARDS;
325                         flags |= PFLAG_IGNOREFIELDS;
326                         if (member->putOnMap(new_place, new_x, new_y, 
327                                              2 * size, flags))
328                                 continue;
329
330                         // Try again, ignoring terrain.
331                         flags |= PFLAG_IGNORETERRAIN;
332                         if (member->putOnMap(new_place, new_x, new_y, 
333                                              2 * size, flags))
334                                 continue;
335
336                         // Ok, now that should have worked!
337                         assert(0);
338                 }
339         }
340
341 // I've messed with this a bit. I think it's confusing (even to me!) to have
342 // the party mode switched automatically. If it felt natural during play it
343 // would be ok, but it's quite the opposite.
344 #undef CONFIG_ENABLE_ROUND_ROBIN_ON_ENTRANCE_TO_HOSTILE_PLACE
345 #ifdef CONFIG_ENABLE_ROUND_ROBIN_ON_ENTRANCE_TO_HOSTILE_PLACE
346         // --------------------------------------------------------------------
347         // Set the party mode to "follow" by default, but if hostiles are in
348         // this place then set to "character" mode.
349         // --------------------------------------------------------------------
350
351         if (place_contains_hostiles(new_place, this)) {
352                 enableRoundRobinMode();
353                 combat_set_state(COMBAT_STATE_FIGHTING);                
354         } else {
355                 enableFollowMode();
356                 combat_set_state(COMBAT_STATE_LOOTING);
357         }        
358 #else
359         // --------------------------------------------------------------------
360         // Set the party mode to "follow" by default. If hostiles are present
361         // the user can opt to engage them manually. If hostiles are present
362         // but not visible it's confusing/annoying when the camera does not
363         // follow the party leader. This is especially true when there is only
364         // one party member. 
365         // --------------------------------------------------------------------
366         enableFollowMode();
367         if (place_contains_hostiles(new_place, this)) {
368                 combat_set_state(COMBAT_STATE_FIGHTING);                
369         }
370 #endif
371         endTurn();
372
373 }
374
375 enum MoveResult PlayerParty::try_to_enter_subplace_from_edge(
376         struct place *subplace, int dx, int dy)
377 {
378         int new_x;
379         int new_y;
380         int dir;
381
382
383         // --------------------------------------------------------------------
384         // There should be no way to get here unless we are already in party
385         // mode, which means we are in the wilderness. And the destination
386         // should never be another wilderness.
387         // --------------------------------------------------------------------
388
389         assert(place_is_wilderness(getPlace()));
390         assert(!place_is_wilderness(subplace));
391
392         // --------------------------------------------------------------------
393         // Entering a subplace REQUIRES a direction so I know which edge of the
394         // subplace the party should enter from. If we don't have one then
395         // prompt the user to get one.
396         // --------------------------------------------------------------------
397
398         if (dx == 0 && dy == 0) {
399                 cmdwin_spush("Enter");
400                 dir = ui_get_direction();
401         } else {
402                 dir = vector_to_8facing(dx, dy);
403         }
404
405         // --------------------------------------------------------------------
406         // Get the entry coordinates from the subplace.
407         // --------------------------------------------------------------------
408
409         switch (dir) {
410         case CANCEL:
411                 return UserCanceled;
412         case HERE:
413                 return NoDestination;
414         default:
415                 if (place_get_edge_entrance(subplace, dir, &new_x, &new_y))
416                         return NoDestination;
417                 break;
418         }
419
420         dx = directionToDx(dir);
421         dy = directionToDy(dir);
422
423         relocate(subplace, new_x, new_y);
424
425         return MovedOk;
426 }
427
428 enum MoveResult PlayerParty::try_to_move_off_map(struct move_info * info)
429 {
430          
431         // Yes, I'm making the following unconditional with no further checks.
432         // The parent tile is _always_ and _unconditionally_ passable.
433         // Consider everything that could make that tile impassable:
434         //   --Terrain on parent map... don't care
435         //   --Autoportals leading elsewhere... ignore them
436         //   --Npc's... they aren't allowed on town tiles in the wilderness,
437         //     and if one sneaks through ignore it
438         //   --Fields... unlikely, and don't care
439         //   --Vehicles (when player is already in one)... ignore them (and
440         //     don't allow player to abandon a vehicle over a town, otherwise
441         //     we can leak vehicles since consecutive abandonments will 
442         //     clobber previous ones)
443         // See notes on the ship problem in discussion #1 of doc/GAME_RULES
444
445         if (! info->place->location.place) {
446                 return OffMap;
447         }
448
449         relocate(info->place->location.place, 
450                  info->place->location.x, 
451                  info->place->location.y);
452
453         return MovedOk;
454 }
455
456 MoveResult PlayerParty::move(int newdx, int newdy)
457 {
458         struct move_info info;
459         struct combat_info cinfo;
460         bool teleport = (abs(newdx) > 1 || abs(newdy) > 1);
461
462         mapSetDirty();
463         cmdwin_clear();
464
465         // Cache the requested direction. Can't remember what we use this for
466         // or if it's still necessary.
467         dx = newdx;
468         dy = newdy;
469
470         // Change vehicle facing. This might consume a turn in which case
471         // that's all we'll do.
472         if (!teleport && turn_vehicle())
473                 return ChangedFacing;
474
475         // Check the consequences of moving to the target tile.
476         memset(&info, 0, sizeof(info));
477         info.place = getPlace();
478         info.x = x + dx;
479         info.y = y + dy;
480         info.dx = dx;
481         info.dy = dy;
482         switch (check_move_to(&info)) {
483
484         case move_ok:
485         {
486                 int mv_cost = 0;
487
488                 // No complications. Update the turn counter based on player
489                 // speed and terrain difficulties then move the player.
490                 mv_cost = place_get_diagonal_movement_cost(info.place, x, y, info.x, info.y, this,0);
491                                         relocate(info.place, info.x, info.y);          
492                 if (vehicle)
493                         mv_cost *= vehicle->getMovementCostMultiplier();
494                 decActionPoints(mv_cost);
495
496                 extern int DeveloperMode;
497                 if (DeveloperMode) {
498                     log_msg("mv_cost=%d\n", mv_cost);
499                 }
500
501                 // none of this is used atm
502                 //
503                 // // reload mv_cost because diagonal movement shouldnt affect 'very slow' etc
504                 //mv_cost = place_get_movement_cost(info.place, info.x, info.y, this,0);
505                 //if (vehicle)
506                 //        mv_cost *= vehicle->getMovementCostMultiplier();                
507                 //if (mv_cost < getSpeed()) {
508                 //        progress = "";
509                 //} else if (mv_cost < (getSpeed() * 2)) {
510                 //        progress = "-slow";
511                 //} else {
512                 //        progress = "-very slow";
513                 //}
514
515                //consolePrint("Move %s%s [%d AP]\n", 
516                //               directionToString(vector_to_8facing(dx, dy)),
517                //               progress, mv_cost);
518
519                 return MovedOk;
520         }
521
522         case move_off_map:
523                 return try_to_move_off_map(&info);
524                 return OffMap;
525
526         case move_occupied:
527                 // Occupied by a friendly npc party. If they were unfriendly
528                 // we'd be going into combat.
529                 return WasOccupied;
530
531         case move_impassable:
532                 // Impassable terrain.
533                 return WasImpassable;
534
535         case move_not_in_vehicle:
536                 return NotInVehicle;
537
538         case move_enter_combat:
539                 // Handle combat (possible multiple combats) until we're all
540                 // done with them.
541                 memset(&cinfo, 0, sizeof(cinfo));
542                 cinfo.move = &info;
543
544                 // ------------------------------------------------------------
545                 // Enter combat on the current square, not the square we're
546                 // trying to move onto.
547                 // ------------------------------------------------------------
548
549                 info.x = getX();
550                 info.y = getY();
551                 info.px = getX();
552                 info.py = getY();
553
554                 combat_enter(&cinfo);
555
556                 endTurn();
557                 return MovedOk;
558
559         case move_enter_subplace:
560
561 #if OLD_PRE_ENTRY_INVOCATION
562                 // Going to try and move this call to place_enter()... as I
563                 // recall I put this here to allow an on-entry hook to prompt
564                 // the player to see if he really wants to enter.
565
566                 // run the place's pre-entry hook, if applicable
567                 if (info.subplace->pre_entry_hook &&
568                     ! closure_exec(info.subplace->pre_entry_hook, "pp", 
569                                    info.subplace, this))
570                         return UserCanceled;
571 #endif
572                 return try_to_enter_subplace_from_edge(info.subplace, info.dx, 
573                                                        info.dy);
574
575         default:
576                 // no other results expected
577                 assert(false);
578                 return NotApplicable;
579         }
580 }
581
582 struct sprite *PlayerParty::getSprite(void)
583 {
584         if (vehicle)
585                 return vehicle->getSprite();
586
587         return sprite;
588 }
589
590 char *PlayerParty::get_movement_description(void)
591 {
592         if (!vehicle)
593                 return mv_desc;
594         return vehicle->getMvDesc();
595 }
596
597 sound_t *PlayerParty::get_movement_sound(void)
598 {
599         if (vehicle) {
600                 return vehicle->get_movement_sound();
601         }
602         return mv_sound;
603 }
604
605 bool PlayerParty::add(class ObjectType * type, int quantity)
606 {
607         if (!quantity)
608                 return true;
609
610         log_begin("");
611         type->describeType(quantity);
612         log_end("¤ò¼ê¤ËÆþ¤ì¤¿¡£");
613
614         return inventory->add(type, quantity);
615 }
616
617 bool PlayerParty::takeOut(ObjectType *type, int q)
618 {
619         // Some types can be in more than one category, so remove from all.
620         log_begin("");
621         type->describeType(q);
622         log_end("¤ò¼º¤Ã¤¿¡£");
623         return inventory->takeOut(type, q);
624 }
625
626 static bool player_member_rest_one_hour(class Character * pm, void *data)
627 {
628         if (pm->isAsleep())
629                 pm->rest(1);
630         return false;
631 }
632
633 void PlayerParty::exec()
634 {
635
636         if (allDead())
637                 return;
638
639         // NOTE: by running startTurn() after this we are skipping the party
640         // members' start-of-party-turn hooks when resting. That's probably not
641         // desirable.
642
643         if (isResting()) {
644
645                 /* After each hour of rest heal/restore party members */
646                 if (clock_alarm_is_expired(&rest_alarm)) {
647                         forEachMember(player_member_rest_one_hour, NULL);
648                         clock_alarm_set(&rest_alarm, 60);
649                 }
650
651                 if (clock_alarm_is_expired(&wakeup_alarm)) {
652                         endResting();
653                 }
654
655                 return;
656         }
657
658         startTurn();      
659         
660         absorbMemberAPDebt();
661         
662         /* Loiter */
663         if (isLoitering())
664         {
665                                 if (clock_alarm_is_expired(&wakeup_alarm))
666                                 {
667                                         endLoitering();
668                                 }
669                                 endTurn();
670         }  
671
672         if (action_points > 0 && ! isDestroyed()) {        
673
674                 /* In party mode increment the turn count whenever the player
675                  * moves. I'm assuming he'll move at most once per turn. */
676                 session_inc_turn_count();
677                 foogodRepaint();
678                 
679                 ctrl(this);
680
681                 if (Session->reloaded)
682                         /* Hack: this object has been destroyed with the old
683                          * session. Leave now! */
684                         return;
685         }
686
687         endTurn();
688 }
689
690 bool PlayerParty::allDead(void)
691 {
692         int count = 0;
693         forEachMember(pc_check_if_alive, &count);
694         return (count == 0);
695 }
696
697 bool PlayerParty::immobilized(void)
698 {
699         int count = 0;
700         forEachMember(pc_check_if_not_immobilized, &count);
701         return (count == 0);        
702 }
703
704 struct VradInfo {
705         int vrad;
706         int light;
707 };
708
709 bool myGetBestVisionRadius(class Character * c, void *data)
710 {
711         struct VradInfo *info = (struct VradInfo *) data;
712         info->vrad = max(info->vrad, c->getVisionRadius());
713         info->light = max(info->light, c->getLight());
714         return false;
715 }
716
717 int PlayerParty::getLight()
718 {
719         struct node *entry;
720         class Character *member;
721
722         light = 0;
723
724         FOR_EACH_MEMBER(entry, member) {
725                 light += member->getLight();
726         }
727
728         return light;
729 }
730
731 int PlayerParty::getVisionRadius()
732 {
733         struct VradInfo info;
734
735         // Scan all party members to find the best light source and the best
736         // eyes. They needn't be from the same member since I assume they are
737         // traveling close enough to share their light sources with each other.
738         info.vrad = 0;
739         info.light = 0;
740         forEachMember(myGetBestVisionRadius, &info);
741
742         // hack -- should replace this with a routine for getting the ambient
743         // light from the local environment (place?)
744         assert(getPlace());
745         if (!getPlace()->underground)
746                 info.light += sky_get_ambient_light(&Session->sky);
747
748         // Set the vision radius to the minimum of the best available light
749         // radius or the best available vision radius of all party members
750         light = max(info.light, MIN_PLAYER_LIGHT);
751
752
753         // left off here
754
755         return min(info.vrad, MAX_VISION_RADIUS);
756 }
757
758 PlayerParty::PlayerParty()
759 {
760         dx                 = 0;
761         dy                 = -1;
762         sprite             = 0;
763         speed              = 0;
764         vehicle            = 0;
765         turns              = 0;
766         mv_desc            = NULL;
767         mv_sound           = NULL_SOUND;
768         leader             = NULL;
769         light              = 1;
770         food               = 0;
771         view               = 0;
772         onMap              = true;
773         gold               = 0;
774         formation          = 0;
775         campsite_map       = 0;
776         campsite_formation = 0;
777         camping            = false;
778         resting            = false;
779         loitering          = false;
780         leader             = NULL;
781         solo_member        = NULL;
782         control_mode       = PARTY_CONTROL_ROUND_ROBIN;
783         ctrl               = ctrl_party_ui;
784         inventory          = NULL;
785
786         setTurnsToNextMeal(TURNS_PER_FOOD);
787         setBaseFaction(PLAYER_PARTY_FACTION);
788         view = mapCreateView();
789 }
790
791 PlayerParty::PlayerParty(char *_tag,
792                            struct sprite *sprite,
793                            char *movement_desc, sound_t *movement_sound,
794                            int _food, int _gold,
795                            struct formation *_formation, 
796                            struct terrain_map *_camping_map,
797                            struct formation *_camping_formation)
798 {
799         /* Do standard initialization first. */
800         dx                 = 0;
801         dy                 = -1;
802         speed              = 0;
803         vehicle            = 0;
804         turns              = 0;
805         leader             = NULL;
806         light              = 1;
807         food               = _food;
808         view               = 0;
809         gold               = _gold;
810         formation          = _formation;
811         campsite_map       = _camping_map;
812         campsite_formation = _camping_formation;
813         camping            = false;
814         resting            = false;
815         loitering          = false;
816         leader             = NULL;
817         solo_member        = NULL;
818         control_mode       = PARTY_CONTROL_ROUND_ROBIN;
819         ctrl               = ctrl_party_ui;
820         tag                = 0;
821         inventory          = NULL;
822
823         // --------------------------------------------------------------------
824         // Location (if any) will be set after construction by the loading
825         // code. Initially the party is off-map and on the orphan list.
826         // --------------------------------------------------------------------
827
828         setOnMap(false);
829
830         setTurnsToNextMeal(TURNS_PER_FOOD);
831         setBaseFaction(PLAYER_PARTY_FACTION);
832         view = mapCreateView();
833
834         /* Now use the arguments */
835
836         if (_tag) {
837                 tag = strdup(_tag);
838                 assert(tag);
839         }
840         
841         this->sprite = sprite;
842         if (movement_desc) {
843                 this->mv_desc = strdup(movement_desc);
844                 assert(this->mv_desc);
845         } else {
846                 mv_desc = 0;
847         }
848
849         this->mv_sound = movement_sound;
850 }
851
852 PlayerParty::~PlayerParty()
853 {
854         if (mv_desc)
855                 free(mv_desc);
856
857         obj_dec_ref_safe(inventory);
858
859         // Bugfix: when quitting while on board a vehicle, force the vehicle to
860         // give up its reference to the player (otherwise this causes an
861         // assert in session_del()).
862         if (vehicle) {
863                 vehicle->setOccupant(0);
864                 vehicle->relocate(getPlace(), getX(), getY());
865                 obj_dec_ref(vehicle);
866                 vehicle = NULL;
867         }
868
869         /* fixme: need to somehow cancel those wq jobs setup by player_init? */
870 }
871
872 void PlayerParty::board_vehicle(void)
873 {
874         cmdwin_clear();
875
876         // already in a vehicle so exit
877         if (vehicle) {
878                 log_begin("");
879                 vehicle->describe();
880                 log_end("¤«¤é¹ß¤ê¤¿¡£");
881                 vehicle->setOccupant(0);
882                 vehicle->relocate(getPlace(), getX(), getY());
883                 obj_dec_ref(vehicle);
884                 vehicle = NULL;
885                 mapSetDirty();
886
887                 /* Erase vehicle hull stats. */
888                 foogodRepaint();
889                 return;
890         }
891
892         vehicle = place_get_vehicle(Place, x, y);
893         if (!vehicle) {
894                 return;
895         }
896
897         obj_inc_ref(vehicle);
898
899         log_begin("");
900         vehicle->describe();
901         log_end("¤Ë¾è¤Ã¤¿¡£");
902
903         vehicle->setOccupant(this);
904         vehicle->remove();
905         mapSetDirty();
906
907         /* Show vehicle hull stats. */
908         foogodRepaint();
909
910         /* Prompt the player to name the vehicle so it isn't
911          * garbage-collected. */
912         if (! vehicle->isNamed()) {
913                 ui_name_vehicle(vehicle);
914         }
915 }
916
917 class Character *PlayerParty::get_leader(void)
918 {
919         if (leader == NULL) {
920                 chooseNewLeader();
921         }
922         return leader;
923 }
924
925 void PlayerParty::removeMember(class Character *c)
926 {
927         struct node *entry;
928         class Character *next_member;
929         int index;
930
931         assert(c->party == (class Party*)this);
932
933         // Remove all its readied arms from party inventory.
934                 int armsIndex = 0;
935         for (class ArmsType * weapon = c->enumerateArms(&armsIndex); weapon != NULL; 
936              weapon = c->getNextArms(&armsIndex)) {
937
938                 struct inv_entry *ie;
939
940                 ie = inventory->search(weapon);
941                 assert(ie);
942                 ie->ref--;
943                 takeOut(weapon, 1);
944         }
945
946         // Re-order the indices of the remaining party members
947         for (entry = node_next(c->plnode), index = c->getOrder(); 
948              entry != &members; 
949              entry = node_next(entry), index++) {
950                 next_member = (class Character *)entry->ptr;
951                 next_member->setOrder(index);
952         }
953
954         // Relinquish control.
955         c->setPlayerControlled(false);
956         c->setControlMode(CONTROL_MODE_AUTO);
957
958         // remove its view
959         c->rmView();
960         
961         // Unhook it from the party
962         Party::removeMember(c);
963 }
964
965 bool PlayerParty::addMember(class Character * c)
966 {
967         // Note: this is called so early in startup that I can't touch the
968         // paint routines in here. Callers will have to update the map and
969         // status if necessary.
970
971         assert(!c->isPlayerControlled());
972
973         // Hook it to the party
974         Party::addMember(c);
975
976         // Make sure it's not going to try and run a schedule
977         c->setSchedule(NULL);
978
979         // Set special player-controlled flag
980         c->setPlayerControlled(true);
981
982         // gmcnutt: added this as a hack to support quickly determining if a
983         // character belongs to the player party.
984         c->party = (Party*)this;
985
986         // Can't think of any reason why a char should be on the orphan list
987         assert(! c->handle);
988
989         if (NULL == c->getView())
990                 c->setView(mapCreateView());
991
992         // Loop over all readied weapons and add them to player inventory. Also
993         // must set the refcount once they are in inventory.
994
995         int armsIndex = 0;
996         for (class ArmsType * weapon = c->enumerateArms(&armsIndex);
997              weapon != NULL; weapon = c->getNextArms(&armsIndex)) {
998
999                 struct inv_entry *ie;
1000
1001                 add(weapon, 1);
1002                 ie = inventory->search(weapon);
1003                 assert(ie);
1004                 ie->ref++;
1005
1006         }
1007
1008         // Note: leave the readied arms as-is and character inventory as-is for
1009         // now.
1010
1011         // --------------------------------------------------------------------
1012         // Reevaluate leadership with the new member added to the group.
1013         // --------------------------------------------------------------------
1014         if (! c->engagedInTask()) {
1015             switch (getPartyControlMode()) {
1016             case PARTY_CONTROL_FOLLOW:
1017                 if (c != get_leader()) {
1018                     c->setControlMode(CONTROL_MODE_FOLLOW);
1019                 }
1020                 break;
1021                 
1022             case PARTY_CONTROL_SOLO:
1023                 c->setControlMode(CONTROL_MODE_IDLE);
1024                 break;
1025                 
1026             case PARTY_CONTROL_ROUND_ROBIN:
1027                 c->setControlMode(CONTROL_MODE_PLAYER);
1028                 break;
1029                 
1030             default:
1031                 assert(false);
1032                 break;
1033             }
1034         }
1035
1036         // Call statusSetMode() to force it to re-evaluate the necessary screen
1037         // size for showing the party.
1038         statusSetMode(ShowParty);
1039
1040         // Force a repaint on the status window.
1041         statusRepaint();
1042
1043         return true;
1044
1045 }
1046
1047 void PlayerParty::paint(int sx, int sy)
1048 {
1049         if (vehicle)
1050                 vehicle->paint(sx, sy);
1051         else
1052                 Object::paint(sx, sy);
1053 }
1054
1055 const char *PlayerParty::getName()
1056 {
1057         return "Á´°÷";
1058 }
1059
1060 bool PlayerParty::isVisible()
1061 {
1062         return true;
1063 }
1064
1065 void PlayerParty::describe()
1066 {
1067         log_continue("%s", getName());
1068 }
1069
1070 struct formation *PlayerParty::get_formation()
1071 {
1072         if (vehicle && vehicle->get_formation())
1073                 return vehicle->get_formation();
1074         if (camping && campsite_formation)
1075                 return campsite_formation;
1076         return formation;
1077 }
1078
1079 int PlayerParty::get_num_living_members(void)
1080 {
1081         int count = 0;
1082         forEachMember(pc_check_if_alive, &count);
1083         return count;
1084 }
1085
1086 class Character *PlayerParty::get_first_living_member(void)
1087 {
1088         class Character *pc = NULL;
1089         forEachMember(pc_get_first_living, &pc);
1090         return pc;
1091 }
1092
1093 void PlayerParty::beginLoitering(int hours)
1094 {
1095         struct node *entry = 0;
1096         class Character *member = 0;
1097
1098         assert(hours > 0);
1099
1100         log_begin_group();
1101         log_msg("¤¦¤í¤¦¤í¤·¤Æ¤¤¤ë¡Ä");
1102         FOR_EACH_MEMBER(entry, member) {
1103                 member->beginLoitering(hours);
1104         }
1105         log_end_group();
1106
1107         clock_alarm_set(&wakeup_alarm, hours * 60);
1108         loitering = true;
1109
1110         /* Bugfix for [ 1629974 ] "loitering in wilderness uses too much
1111          * food". We want the acceleration to be one hour per turn at the
1112          * current map scale. CAMPING_TIME_ACCELERATION is appropriate for a
1113          * town-scale wilderness combat map (where camping typically occurs),
1114          * but party loitering is done at wilderness scale. */
1115         session_set_time_accel((float)CAMPING_TIME_ACCELERATION
1116                                / (float)place_get_scale(getPlace()));
1117 }
1118
1119 bool PlayerParty::isLoitering()
1120 {
1121         return loitering;
1122 }
1123
1124 void PlayerParty::endLoitering()
1125 {
1126         struct node *entry;
1127         class Character *member;
1128
1129         loitering  = false;
1130         session_set_time_accel(1);
1131         log_begin_group();
1132         FOR_EACH_MEMBER(entry, member) {
1133                 member->endLoitering();
1134         }
1135         enableFollowMode();
1136         log_end_group();
1137 }
1138
1139
1140 void PlayerParty::forceAbortLoitering()
1141 {
1142         endLoitering();
1143         
1144         struct node *entry;
1145         class Character *member;
1146
1147         log_begin_group();
1148         FOR_EACH_MEMBER(entry, member) {
1149                 member->resetActionPoints();
1150         }
1151         log_end_group();
1152 }
1153
1154
1155 static bool member_begin_resting(class Character *member, void *data)
1156 {
1157         member->beginResting(*((int*)data));
1158         return false;
1159 }
1160
1161 void PlayerParty::beginResting(int hours)
1162 {
1163         assert(hours > 0);
1164
1165         log_begin_group();
1166         log_msg("µÙ©¤ò»Ï¤á¤¿¡Ä");
1167         forEachMember(member_begin_resting, &hours);
1168         log_end_group();
1169
1170         statusRepaint();
1171
1172         clock_alarm_set(&wakeup_alarm, hours * 60);
1173         clock_alarm_set(&rest_alarm, 60);
1174         resting   = true;
1175
1176         mapBlackout(1);
1177         mapSetDirty();
1178
1179         // Accelerate time while resting.
1180         session_set_time_accel(CAMPING_TIME_ACCELERATION);
1181 }
1182
1183 bool PlayerParty::isResting()
1184 {
1185         return (resting || camping);
1186 }
1187
1188 void PlayerParty::throw_out_of_bed()
1189 {
1190         assert(isResting());
1191         endResting();
1192 }
1193
1194 class Character *PlayerParty::getMemberAtIndex(int index)
1195 {
1196         struct node *entry;
1197         class Character *member;
1198
1199         FOR_EACH_MEMBER(entry, member) {
1200                 if (!index)
1201                         return member;
1202                 index--;
1203         }
1204
1205         return NULL;
1206 }
1207
1208 static bool member_uncharm(class Character *member, void *data)
1209 {
1210         member->unCharm();
1211         return false;
1212 }
1213
1214 void PlayerParty::unCharmMembers()
1215 {
1216         forEachMember(member_uncharm, NULL);
1217 }
1218
1219 bool PlayerParty::addToInventory(class Object *object)
1220 {
1221         // ---------------------------------------------------------------------
1222         // This is the overloaded generic Object method. For now it is just a
1223         // wrapper for the pre-existing, historical add_to_inventory() method.
1224         //
1225         // Probably about the time I convert the player inventory to use
1226         // objects instead of types I'll remove add_to_inventory() and roll the
1227         // implementation into here.
1228         // ---------------------------------------------------------------------
1229
1230         add(object->getObjectType(), object->getCount());
1231         obj_dec_ref(object);
1232         return true;
1233 }
1234
1235 bool PlayerParty::isCamping()
1236 {
1237         return camping;
1238 }
1239
1240 void PlayerParty::beginCamping(class Character *guard, int hours)
1241 {
1242         struct node *entry;
1243         class Character *member;
1244
1245         camping    = true;
1246         camp_guard = guard;        
1247
1248         if (camp_guard
1249             && ! camp_guard->isDead()
1250             && ! camp_guard->isAsleep())
1251                 camp_guard->beginGuarding(hours);
1252
1253         FOR_EACH_MEMBER(entry, member) {
1254                 if (member != camp_guard)
1255                         member->beginCamping(hours);
1256         }
1257
1258         // Accelerate time while camping.
1259         session_set_time_accel(CAMPING_TIME_ACCELERATION);
1260 }
1261
1262 void PlayerParty::endCamping()
1263 {
1264         struct node *entry;
1265         class Character *member;
1266
1267         if (! isCamping())
1268                 return;
1269
1270         camping    = false;
1271
1272         // Un-accelerate time when done camping.
1273         session_set_time_accel(1);
1274
1275         if (NULL != camp_guard) {
1276                 camp_guard->endGuarding();
1277                 camp_guard = NULL;
1278         }
1279
1280         FOR_EACH_MEMBER(entry, member) {
1281                 if (member != camp_guard)
1282                         member->endCamping();
1283         }
1284
1285 }
1286
1287 void PlayerParty::ambushWhileCamping()
1288 {
1289         struct node *entry;
1290         class Character *member;
1291
1292         camping = false;
1293
1294         // Un-accelerate time when done camping.
1295         session_set_time_accel(1);
1296
1297         FOR_EACH_MEMBER(entry, member) {
1298
1299                 // ------------------------------------------------------------
1300                 // If there's a guard then he/she/it will wake everybody else
1301                 // up.
1302                 // ------------------------------------------------------------
1303                 
1304                 if (camp_guard != NULL) {
1305                         member->endResting();
1306                 }
1307
1308                 // ------------------------------------------------------------
1309                 // Since there is no guard each member will roll to wake up.
1310                 // ------------------------------------------------------------
1311
1312                 else {
1313                         member->ambushWhileCamping();
1314                 }
1315         }
1316
1317         if (camp_guard)
1318                 camp_guard->endGuarding();
1319 }
1320
1321 void PlayerParty::endResting()
1322 {
1323         struct node *entry;
1324         class Character *member;
1325
1326         resting   = false;
1327
1328         // Un-accelerate time when done resting.
1329         session_set_time_accel(1);
1330
1331         log_begin_group();
1332         FOR_EACH_MEMBER(entry, member) {
1333                 member->endResting();
1334         }
1335         enableFollowMode();
1336         log_end_group();
1337
1338         mapBlackout(0);
1339         mapSetDirty();
1340 }
1341
1342 // -----------------------------------------------------------------------------
1343 //
1344 //      Party control mode functions
1345 //
1346 // -----------------------------------------------------------------------------
1347
1348 static bool member_set_control_mode(class Character *member, void *data)
1349 {
1350     if (member->isPlayerControlled()
1351         && ! member->engagedInTask()
1352         ) {
1353         member->setControlMode(*((enum control_mode*)data));
1354     }
1355     return false;
1356 }
1357
1358 enum party_control PlayerParty::getPartyControlMode()
1359 {
1360         return control_mode;
1361 }
1362
1363 void PlayerParty::disableCurrentMode()
1364 {
1365         if (solo_member) {
1366                 solo_member->setSolo(false);
1367                 solo_member = NULL;
1368         }
1369
1370         if (leader) {
1371                 leader->setLeader(false);
1372                 leader = NULL;
1373         }
1374 }
1375
1376 void PlayerParty::enableFollowMode()
1377 {
1378         enum control_mode mode = CONTROL_MODE_FOLLOW;
1379
1380         disableCurrentMode();
1381         forEachMember(member_set_control_mode, &mode);
1382         chooseNewLeader();
1383         if (NULL == leader) {
1384             enableRoundRobinMode();
1385         } else {
1386             control_mode = PARTY_CONTROL_FOLLOW;
1387             foogod_set_title("ÄÉÀ×: %s", leader->getName());
1388             foogodRepaint();
1389         }
1390
1391 }
1392
1393 void PlayerParty::enableRoundRobinMode()
1394 {
1395         enum control_mode mode = CONTROL_MODE_PLAYER;
1396
1397         disableCurrentMode();
1398         forEachMember(member_set_control_mode, &mode);
1399         control_mode = PARTY_CONTROL_ROUND_ROBIN;
1400         foogod_set_title("ÄÉÀ×: <̤Äê>");
1401         foogodRepaint();
1402 }
1403
1404 void PlayerParty::enableSoloMode(class Character *solo)
1405 {
1406         enum control_mode mode = CONTROL_MODE_IDLE;
1407
1408         assert(solo->party == (class Party*)this);
1409
1410         disableCurrentMode();
1411         forEachMember(member_set_control_mode, &mode);
1412         solo->setSolo(true);
1413         solo_member = solo;
1414         control_mode = PARTY_CONTROL_SOLO;
1415         foogod_set_title("ñÆÈ: %s", solo->getName());
1416         foogodRepaint();
1417 }
1418
1419 void PlayerParty::chooseNewLeader()
1420 {
1421         if (NULL != leader) {
1422                 leader->setLeader(false);
1423                 leader = NULL;
1424         }
1425
1426         struct node *entry;
1427         class Character *member;
1428
1429         FOR_EACH_MEMBER(entry, member) {
1430                 if (member->canBeLeader()) {
1431                         setLeader(member);
1432                         break;
1433                 }
1434         }
1435
1436         if (NULL != leader) {
1437                 leader->setLeader(true);
1438                 if (PARTY_CONTROL_FOLLOW == control_mode) {
1439                     foogod_set_title("ÄÉÀ×: %s", leader->getName());
1440                     foogodRepaint();
1441                 }
1442         }
1443 }
1444
1445 void PlayerParty::setLeader(class Character *character)
1446 {
1447         leader = character;
1448 }
1449
1450 bool PlayerParty::rendezvous(struct place *place, int rx, int ry)
1451 {
1452         bool abort = false;
1453         bool done;
1454         int max_path_len;
1455         struct node *entry;
1456         class Character *member;
1457
1458         assert(NULL != leader);
1459
1460         // --------------------------------------------------------------------
1461         // If any member cannot find a path at least this short than rendezvous
1462         // fails
1463         // --------------------------------------------------------------------
1464
1465         max_path_len = 10;
1466
1467         // --------------------------------------------------------------------
1468         // Center the camera on the rendezvous point.
1469         // --------------------------------------------------------------------
1470
1471         mapCenterCamera(rx, ry);
1472         mapUpdate(0);
1473
1474         // --------------------------------------------------------------------
1475         // Have each party member find and store a path to the rendezvous
1476         // point.
1477         // --------------------------------------------------------------------
1478
1479         FOR_EACH_MEMBER(entry, member) {
1480
1481                 struct astar_search_info as_info;
1482
1483                 // ------------------------------------------------------------
1484                 // If the member already has a cached path then clean it up.
1485                 // ------------------------------------------------------------
1486                 if (member->cachedPath) {
1487                         astar_path_destroy(member->cachedPath);
1488                         member->cachedPathPlace = NULL;
1489                         member->cachedPath = NULL;
1490                 }
1491
1492                 if (NULL == member 
1493                     || member->isDead() 
1494                     || !member->isOnMap() 
1495                     || member == leader 
1496                     || (member->getX() == rx 
1497                         && member->getY() == ry))
1498                         continue;
1499
1500                 /* The following works for sleeping, but in general is not a
1501                  * good solution. What about paralyzation, or other effects
1502                  * unknown to the kernel? What will happen is these effects
1503                  * will be ignored in the code below. Although technically not
1504                  * correct behavior, it shouldn't crash or make the game
1505                  * unplayable. */
1506                 if (member->isAsleep()
1507                     || member->engagedInTask()
1508                     || ! member->isPlayerControlled()
1509                     ) {
1510                         abort = true;
1511                         continue;
1512                 }
1513
1514                 memset(&as_info, 0, sizeof (as_info));
1515                 as_info.x0    = member->getX();
1516                 as_info.y0    = member->getY();
1517                 as_info.x1    = rx;
1518                 as_info.y1    = ry;
1519                 as_info.flags = PFLAG_IGNOREBEINGS;
1520                 member->cachedPath = place_find_path(place, &as_info, 
1521                                                member);
1522
1523                 if (!member->cachedPath) {
1524                         log_msg("%s¤Ï½¸¹ç¤Ç¤­¤Ê¤¤¡ª", 
1525                                      member->getName());
1526                         abort = true;
1527                 }
1528                 else if (max_path_len > 0 && 
1529                          member->cachedPath->len > max_path_len) {
1530                         log_msg("%s¤Ï±ó¤¹¤®¤ë¡ª", 
1531                                      member->getName());
1532                         abort = true;
1533                 }
1534         }
1535
1536         // --------------------------------------------------------------------
1537         // If anyone could not find a path then abort.
1538         // --------------------------------------------------------------------
1539
1540         if (abort) {
1541                 FOR_EACH_MEMBER(entry, member) {
1542                         if (member->cachedPath) {
1543                                 astar_path_destroy(member->cachedPath);
1544                                 member->cachedPath = 0;
1545                         }
1546                 }
1547                 return false;
1548         }
1549
1550         // --------------------------------------------------------------------
1551         // Otherwise everyone has a path, so have them each take turns
1552         // following their own path to the rendezvous point.
1553         // --------------------------------------------------------------------
1554
1555         done = false;
1556         while (!done) {
1557                 done = true;
1558                 //consolePrint(".");
1559                 FOR_EACH_MEMBER(entry, member) {
1560
1561                         struct astar_node *tmp;
1562
1563                         // already arrived in an earlier iteration
1564                         if (!member->cachedPath)
1565                                 continue;
1566
1567                         // should always be at least two nodes
1568                         assert(member->cachedPath->next);
1569
1570                         // arrived
1571                         if (member->cachedPath->next->x == rx && 
1572                             member->cachedPath->next->y == ry) {
1573                                 astar_node_destroy(member->cachedPath);
1574                                 member->cachedPath = 0;
1575                                 //member->remove();   // try this... seems ok
1576                                 continue;
1577                         }
1578
1579                         done = false;
1580
1581                         // move one step
1582                         member->move(
1583                                 member->cachedPath->next->x - member->getX(), 
1584                                 member->cachedPath->next->y - member->getY());
1585
1586                         // clean up used path node
1587                         tmp = member->cachedPath;
1588                         member->cachedPath = member->cachedPath->next;
1589                         astar_node_destroy(tmp);
1590
1591                         // Bugfix: after rendezvous party members sometimes
1592                         // have a heavy action point debt, penalizing them in
1593                         // the new place. Zero out the debt during rendezvous
1594                         // to prevent that.
1595                         member->resetActionPoints();
1596
1597                         mapUpdate(0);
1598                 }
1599         }
1600
1601         //consolePrint("Ok!\n");
1602
1603         return true;
1604
1605 }
1606
1607 int PlayerParty::getContext(void)
1608 {
1609         return (isOnMap() ? CONTEXT_WILDERNESS : CONTEXT_TOWN);
1610 }
1611
1612 void PlayerParty::addView()
1613 {
1614         attachCamera(true);
1615         mapSetPlace(getPlace());
1616         Object::addView();
1617 }
1618
1619 struct place *PlayerParty::getPlaceFromMembers(void)
1620 {
1621         struct node *elem;
1622         class Character *member;
1623
1624         member = get_leader();
1625
1626         if (member)
1627                 return member->getPlace();
1628
1629         FOR_EACH_MEMBER(elem, member) {
1630                 if (member->isOnMap()) {
1631                         return member->getPlace();
1632                 }
1633         }
1634
1635         return 0;
1636 }
1637
1638 void PlayerParty::startSession(void)
1639 {
1640         struct node *elem;
1641         class Character *member;
1642
1643
1644         if (isOnMap())
1645                 return;
1646
1647         // --------------------------------------------------------------------
1648         // Not on the map, so we must be in a small-scale place. At least one
1649         // of the members needs to be on the map or I can't figure out where
1650         // the starting place is. Once I know, I can setup the map viewer and
1651         // add all the member views.
1652         // --------------------------------------------------------------------
1653        
1654         Place = getPlaceFromMembers();
1655
1656         if (! Place)
1657                 return;
1658
1659         assert(Place);
1660         mapSetPlace(Place);
1661         mapSetDirty();
1662         setPlace(Place);
1663         
1664         FOR_EACH_MEMBER(elem, member) {
1665                 if (member->isOnMap()) {
1666                         member->addView();
1667                 }
1668         }
1669
1670         // --------------------------------------------------------------------
1671         // Set the party mode to "follow" by default, but if hostiles are in
1672         // this place then set to "character" mode.
1673         // --------------------------------------------------------------------
1674
1675         if (place_contains_hostiles(getPlace(), this)) {
1676                 enableRoundRobinMode();
1677                 combat_set_state(COMBAT_STATE_FIGHTING);
1678         } else {
1679                 enableFollowMode();
1680                 combat_set_state(COMBAT_STATE_DONE);
1681         }        
1682
1683 }
1684
1685 void PlayerParty::setOnMap(bool val)
1686 {
1687         if (val == isOnMap())
1688                 return;
1689
1690         Object::setOnMap(val);
1691
1692         // --------------------------------------------------------------------
1693         // If the party is going from off-map to on, then remove it from the
1694         // orphan list. If the opposite then add it.
1695         // --------------------------------------------------------------------
1696
1697         if (val) {
1698                 assert(handle);
1699                 session_rm_obj(Session, this);
1700                 handle = 0;
1701         } else {
1702                 assert(! handle);
1703                 session_add_obj(Session, this, player_dtor, player_save, NULL);
1704         }
1705 }
1706
1707 void player_dtor(void *val)
1708 {
1709         class PlayerParty *party = (class PlayerParty*)val;
1710         obj_dec_ref(party);
1711 }
1712
1713 void player_save(save_t *save, void *val)
1714 {
1715         ((class PlayerParty*)val)->save(save);
1716 }
1717
1718 void PlayerParty::save(save_t *save)
1719 {
1720         save->enter(save, "(let ((kplayer ");
1721
1722         save->enter(save, "(kern-mk-player\n");
1723         if (tag)
1724                 save->write(save, "'%s\n", tag);
1725         else
1726                 save->write(save, "nil\n");
1727         save->write(save, "%s\n", sprite_get_tag(this->sprite));
1728         save->write(save, "\"%s\"\n", this->mv_desc);
1729         if (NULL_SOUND != mv_sound)
1730                 save->write(save, "%s\n", sound_get_tag(this->mv_sound));
1731         else
1732                 save->write(save, "nil\n");
1733         save->write(save, "%d %d\n", food, gold);
1734         save->write(save, "%d ;; turns to next meal\n", 
1735                     turns_to_next_meal);
1736         save->write(save, "%s\n", 
1737                 this->formation ? this->formation->tag : "nil");
1738         save->write(save, "%s\n", 
1739                 this->campsite_map ? this->campsite_map->tag : "nil");
1740         save->write(save, "%s\n", 
1741                 this->campsite_formation ? 
1742                 this->campsite_formation->tag : "nil");
1743
1744         if (vehicle)
1745                 vehicle->save(save);
1746         else
1747                 save->write(save, "nil ; player's vehicle\n");
1748
1749         inventory->save(save);
1750
1751         if (list_empty(nodelst(&this->members))) {
1752                 save->write(save, "nil\n");
1753         } else {
1754                 struct node *elem;
1755                 class Character *ch;
1756
1757                 save->enter(save, "(list\n");
1758                 FOR_EACH_MEMBER(elem,ch) {
1759                         char_save(save, ch);
1760                 }
1761                 save->exit(save, ")  ; list of party members\n");
1762         }
1763
1764         save->exit(save, ")))\n"); // end ((kplayer (kern-mk-player ...)))
1765
1766         if (getGob()) {
1767                 save->enter(save, "(bind kplayer ");
1768                 gob_save(getGob(), save);
1769                 save->exit(save, ")\n");
1770         }
1771
1772         save->exit(save, ")\n"); // end (let ...) block
1773 }
1774
1775 bool PlayerParty::addFood(int amount)
1776 {
1777         if (amount == 0)
1778                 return true;
1779
1780         if (amount > 0)
1781                 log_msg("%d¤Î¿©ÎÁ¤ò¼ê¤ËÆþ¤ì¤¿¡£", amount);
1782         else
1783                 log_msg("%d¤Î¿©ÎÁ¤ò¼º¤Ã¤¿¡£", amount);
1784
1785         food += amount;
1786         if (food < 0)
1787                 food = 0;
1788         foogodRepaint();
1789
1790         return true;
1791 }
1792
1793 bool PlayerParty::addGold(int amount)
1794 {
1795         if (amount == 0)
1796                 return true;
1797
1798         if (amount > 0)
1799                 log_msg("%d¤Î¶â¤òÆÀ¤¿¡£", amount);
1800         else
1801                 log_msg("%d¤Î¶â¤ò¼º¤Ã¤¿¡£", -amount);
1802
1803         gold += amount;
1804         if (gold < 0)
1805                 gold = 0;
1806         foogodRepaint();
1807
1808         return true;
1809 }
1810
1811 bool PlayerParty::isPlayerControlled()
1812 {
1813         return true;
1814 }
1815
1816 void PlayerParty::advanceTurns(int turns)
1817 {
1818         // Check if its time to eat
1819         turns_to_next_meal -= turns;
1820         if (turns_to_next_meal <= 0) {
1821                 forEachMember(pc_eat_food, 0);
1822                 foogodRepaint();
1823                 turns_to_next_meal += TURNS_PER_FOOD;
1824         }
1825 }
1826
1827 void PlayerParty::setTurnsToNextMeal(int turns)
1828 {
1829         turns_to_next_meal = turns;
1830 }
1831
1832 bool PlayerParty::hasInInventory(class ObjectType *type)
1833 {
1834         return inventory->search(type) != NULL;
1835 }
1836
1837 void PlayerParty::unrefInventoryObject(ObjectType *type)
1838 {
1839         struct inv_entry *ie = inventory->search(type);
1840         assert(ie);
1841         ie->ref--;
1842 }
1843
1844 void PlayerParty::refInventoryObject(ObjectType *type)
1845 {
1846         struct inv_entry *ie = inventory->search(type);
1847         assert(ie);
1848         ie->ref++;
1849 }
1850
1851 void PlayerParty::setInventoryContainer(Container *val)
1852 {
1853         assert(!inventory);
1854         assert(val);
1855
1856         inventory = val;
1857         obj_inc_ref(inventory);
1858 }
1859
1860 void PlayerParty::addExperience(int val)
1861 {
1862         struct node *entry;
1863         class Character *member;
1864
1865         FOR_EACH_MEMBER(entry, member) {
1866                 if (!member->isDead()) {
1867                         member->addExperience(val);
1868                 }
1869         }
1870 }
1871
1872 bool PlayerParty::canSeeLocation(struct place *place, int x, int y)
1873 {
1874         // fixme -- ref naz.scm (any-player-party-member-visible?)
1875         return false;
1876 }
1877
1878 /* shifts currently wielded items to the top of the equipment list */
1879 void PlayerParty::sortReadiedItems(class Character * member)
1880 {
1881         struct inv_entry *ie;
1882         int armsIndex = 0;
1883         for (class ArmsType * weapon = member->enumerateArms(&armsIndex); weapon != NULL; 
1884              weapon = member->getNextArms(&armsIndex)) {
1885
1886                 ie = inventory->search(weapon);
1887                 assert(ie);
1888                 inventory->moveToFront(ie);
1889         }
1890 }
1891
1892 class Container *PlayerParty::getInventory()
1893 {
1894         // yes, I know it's public, but this is polymorphic with the Party base class
1895         return inventory;
1896 }