#include <iostream>
#include <vector>
#include <list>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cassert>
using namespace std;
struct Role;
enum Card {P, K, D, F, N, W, J, Z};
enum Status {MP, ZP, FP, LFP, UK};
enum Behavior {Kind, Hosti, Like_Hosti};
int n, m, living;
int pos_id[10];
int FP_cnt;
vector<Card> card_heap;
void cause_injury(int source, int target);
void settle_death(int source, int target);
void judge_status(int source, int target, Behavior behavior);
bool ask_J(int role, Behavior behavior);
int next_role(int role);
bool is_unknown(int a);
bool is_friend(int source, int target);
bool is_enemy(int source, int target);
istream & operator>>(istream & is, Status & s);
istream & operator>>(istream & is, Card & c);
ostream & operator<<(ostream & os, Card c);
void game_init();
void game_on();
void game_terminate(Status winner);
int main()
{
game_init();
game_on();
}
struct Role
{
int id, pos;
Status status, known_status;
int health_point, health_limit;
int hand_card[8], armed_card;
list<Card> hand_card_list;
Role() = default;
Role(Status s, int i, Card c1, Card c2, Card c3, Card c4) :
id(i), pos(i), status(s), known_status(UK), health_point(4), health_limit(4),
hand_card{}, armed_card(0), hand_card_list{}
{
pos_id[pos] = id;
if (s == MP)
known_status = MP;
hand_card[c1]++, hand_card[c2]++, hand_card[c3]++, hand_card[c4]++;
hand_card_list.push_back(c1), hand_card_list.push_back(c2), hand_card_list.push_back(c3), hand_card_list.push_back(c4);
}
void get_card(int num)
{
while (num--)
{
Card t = card_heap.back();
card_heap.pop_back();
hand_card[t]++;
hand_card_list.push_back(t);
}
}
void del_card(Card c)
{
for (auto p = hand_card_list.begin(); p != hand_card_list.end(); ++p)
{
if (*p == c)
{
hand_card_list.erase(p);
break;
}
}
}
void play_stage();
void use_P();
void use_K(int b);
void use_F(int b);
void use_N();
void use_W();
void use_Z();
};
Role roles[10];
void Role::play_stage()
{
bool K_used = false;
while (hand_card[P] && health_point < health_limit)
use_P();
while (hand_card[Z])
use_Z();
while (hand_card[W])
use_W();
while (hand_card[N])
use_N();
for (int t = 1, i = next_role(id); t < living; t++, i = next_role(id))
{
if (is_enemy(id, i))
{
while (hand_card[K] && (!K_used || armed_card) && t == 1 && roles[i].health_point)
{
use_K(i);
K_used = true;
}
while (hand_card[F] && roles[i].health_point)
use_F(i);
}
}
}
void Role::use_P()
{
health_point++;
hand_card[P]--, del_card(P);
}
void Role::use_K(int b)
{
hand_card[K]--, del_card(K);
if (roles[b].hand_card[D])
roles[b].hand_card[D]--, roles[b].del_card(D);
else
cause_injury(id, b);
if (is_unknown(id))
judge_status(id, b, Hosti);
}
void Role::use_F(int b)
{
hand_card[F]--, del_card(F);
if (ask_J(b, Kind))
return;
while (true)
{
if (roles[b].hand_card[K] && !(roles[b].status == ZP && status == MP))
roles[b].hand_card[K]--, roles[b].del_card(K);
else
{
cause_injury(id, b);
break;
}
if (hand_card[K])
hand_card[K]--, del_card(K);
else
{
cause_injury(b, id);
break;
}
}
if (is_unknown(id))
judge_status(id, b, Hosti);
}
void Role::use_N()
{
hand_card[N]--, del_card(N);
for (int t = 1, i = next_role(id); t < living; t++, i = next_role(i))
{
if (roles[i].health_point && i != id)
{
if (ask_J(i, Kind))
;
else if (roles[i].hand_card[K])
roles[i].hand_card[K]--, roles[i].del_card(K);
else
cause_injury(id, i);
}
}
}
void Role::use_W()
{
hand_card[W]--, del_card(W);
for (int t = 1, i = next_role(id); t < living; t++, i = next_role(i))
{
if (roles[i].health_point && i != id)
{
if (ask_J(i, Kind))
;
else if (roles[i].hand_card[D])
roles[i].hand_card[D]--, del_card(D);
else
cause_injury(id, i);
}
}
}
void Role::use_Z()
{
armed_card = 1;
hand_card[Z]--, del_card(Z);
}
int next_role(int a)
{
return pos_id[(roles[a].pos + 1) % living];
}
bool is_unknown(int a)
{
return roles[a].known_status == UK || roles[a].known_status == LFP;
}
bool is_friend(int a, int b)
{
return ((roles[b].known_status == MP || roles[b].known_status == ZP) &&
(roles[a].status == MP || roles[a].status == ZP)) ||
(roles[b].known_status == FP && roles[a].known_status == FP);
}
bool is_enemy(int a, int b)
{
return ((roles[b].known_status == MP || roles[b].known_status == ZP) &&
roles[a].status == FP) ||
(roles[b].known_status == FP &&
(roles[b].known_status == MP && roles[a].known_status == ZP)) ||
(roles[b].known_status == LFP && roles[a].known_status == MP);
}
bool ask_J(int a, Behavior o)
{
if (is_unknown(a))
return false;
for (int t = 1, i = a; t <= living; t++, i = next_role(i))
{
if (roles[i].hand_card[J] && ((o == Kind && is_friend(i, a))
|| (o == Hosti && is_enemy(i, a))))
{
roles[i].hand_card[J]--, roles[i].del_card(J);
if (is_unknown(a))
judge_status(i, a, o);
return !ask_J(i, Hosti);
}
}
return false;
}
void cause_injury(int a, int b)
{
roles[b].health_point--;
if (roles[b].health_point == 0)
{
if (roles[b].hand_card[P])
roles[b].use_P();
else
settle_death(a, b);
}
if (is_unknown(a))
judge_status(a, b, Like_Hosti);
}
void settle_death(int a, int b)
{
switch (roles[b].status)
{
case MP:
game_terminate(FP);
break;
case ZP:
if (roles[a].status == MP)
memset(roles[a].hand_card, 0, sizeof(roles[a].hand_card)), roles[a].hand_card_list.clear();
break;
case FP:
FP_cnt--;
if (FP_cnt == 0)
game_terminate(MP);
roles[a].get_card(3);
break;
}
for (int i = 0; i < n; i++)
if (roles[i].pos > roles[b].pos)
pos_id[--roles[i].pos] = i;
living--;
}
void judge_status(int a, int b, Behavior t)
{
switch (t)
{
case Kind:
switch (roles[b].known_status)
{
case MP: case ZP:
roles[a].known_status = ZP;
break;
case FP:
roles[a].known_status = FP;
break;
}
break;
case Hosti:
switch (roles[b].known_status)
{
case MP: case ZP:
roles[a].known_status = FP;
break;
case FP:
roles[a].known_status = ZP;
break;
}
break;
case Like_Hosti:
if (roles[b].known_status == MP)
roles[a].known_status = LFP;
break;
}
}
istream & operator>>(istream & is, Status & s)
{
string str;
is >> str;
switch (str[0])
{
case 'M': s = MP; break;
case 'Z': s = ZP; break;
case 'F': s = FP; break;
}
return is;
}
istream & operator>>(istream & is, Card & c)
{
char ch;
is >> ch;
switch (ch)
{
case 'P': c = P; break;
case 'K': c = K; break;
case 'D': c = D; break;
case 'F': c = F; break;
case 'N': c = N; break;
case 'W': c = W; break;
case 'J': c = J; break;
case 'Z': c = Z; break;
}
return is;
}
ostream & operator<<(ostream & os, Card c)
{
switch (c)
{
case P: os << 'P'; break;
case K: os << 'K'; break;
case D: os << 'D'; break;
case F: os << 'F'; break;
case N: os << 'N'; break;
case W: os << 'W'; break;
case J: os << 'J'; break;
case Z: os << 'Z'; break;
}
return os;
}
void game_init()
{
cin >> n >> m;
living = n;
Status s;
Card c1, c2, c3, c4, c;
for (int i = 0; i < n; i++)
{
cin >> s >> c1 >> c2 >> c3 >> c4;
roles[i] = Role(s, i, c1, c2, c3, c4);
if (s == FP)
FP_cnt++;
}
while (m--)
{
cin >> c;
card_heap.push_back(c);
}
reverse(begin(card_heap), end(card_heap));
}
void game_on()
{
int i = 0;
while (true)
{
roles[i].get_card(2);
roles[i].play_stage();
i = next_role(i);
}
}
void game_terminate(Status winner)
{
if (winner == MP)
cout << "MP\n";
else
cout << "FP\n";
for (int i = 0; i < n; i++)
{
if (roles[i].health_point == 0)
cout << "DEAD\n";
else
{
auto p = roles[i].hand_card_list.begin();
for (int j = 0; j < roles[i].hand_card_list.size(); ++j, ++p)
cout << *p << (j < roles[i].hand_card_list.size() - 1 ? ' ' : '\n');
if (roles[i].hand_card_list.empty())
cout << '\n';
}
}
exit(0);
}