<commit_before>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 512
#define ACK 0
#define NAK 1
#define BUFSIZE 505
#define FILENAME "Testfile"
#define TIMEOUT 100 //in ms
#define WIN_SIZE 16

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
void loadWindow();
bool sendPacket();
bool getGet();

struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
Packet window[16];
int length;
bool dropPck;
bool delayPck;
int toms;
unsigned char b[BUFSIZE];
int base;

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  sendFile();

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  struct timeval timeout;
  timeout.tv_usec = TIMEOUT * 1000;
  toms = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  base = 0;
  dropPck = false;
  calen = sizeof(ca);

  getGet();

  return true;
}

bool getGet(){
	unsigned char packet[PAKSIZE + 1];
	rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
	return (rlen > 0) ? true : false;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == 0) return false; //doesn't matter, only for the old version (netwark)
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        //seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p (false, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

void loadWindow(){
	for(int i = base; i < base + WIN_SIZE; i++) {
		window[i-base] = createPacket(i);
		if(strlen(window[i-base].getDataBuffer()) < BUFSIZE - 1 && window[i-base].getDataBuffer()[0] != 'G') {
			for(++i; i < base + WIN_SIZE; i++){
				window[i-base].loadDataBuffer("\0");
			}
			return;
		}
	}
}

bool sendFile() {
	/*Currently causes the program to only send the first 16 packets of file out
		requires additional code later to sendFile again with updated window*/
	base = 0;
	while(base * BUFSIZE < length) {
		loadWindow();

		cout << "packet " << base << ": " << window[0].str() << endl;

		for(int x = 0; x < WIN_SIZE; x++) {
			p = window[x];
			if(!sendPacket()) continue;
		}
		if(p.str()[0] == '\0') break;
		for(int x = 0; x < WIN_SIZE; x++) {
			if(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
				cout << "=== ACK TIMEOUT" << endl;
				x--;
				continue;
			}

			if(isAck()) {
				handleAck();
			} else {
				handleAck();
				//handleNak(x);
			}

			memset(b, 0, BUFSIZE);
		}
	}

	if(sendto(s, "\0", BUFSIZE, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Final package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
	}
	return true;
}

Packet createPacket(int index){
    cout << endl;
	cout << "=== PACKET CREATION TESTING" << endl;
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);
	cout << "index: " << index << endl;
	cout << "mstr: " << mstr << endl;

	if(mstr.length() < BUFSIZE) {
		cout << "Null terminated mstr." << endl;
		mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (index, mstr.c_str());
}

bool sendPacket(){
	cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	dropPck = pckStatus[0];
	delayPck = pckStatus[1];

	if (dropPck == true) return false;
	if (delayPck == true) p.setAckNack(1);

    if(sendto(s, p.str(), BUFSIZE + 8, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}
bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {
	int ack = boost::lexical_cast<int>(b);
	if(base < ack) base = ack;
	cout << "Window base: " << base << endl;
}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){

  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  packStatus[0] = false;
  packStatus[1] = false;

  if(r <= (lossProb)){
	packStatus[0] = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  packStatus[1] = true;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  //cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<commit_msg>Slim down on testing<commit_after>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 512
#define ACK 0
#define NAK 1
#define BUFSIZE 505
#define FILENAME "Testfile"
#define TIMEOUT 100 //in ms
#define WIN_SIZE 16

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
void loadWindow();
bool sendPacket();
bool getGet();

struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
Packet window[16];
int length;
bool dropPck;
bool delayPck;
int toms;
unsigned char b[BUFSIZE];
int base;

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  sendFile();

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  struct timeval timeout;
  timeout.tv_usec = TIMEOUT * 1000;
  toms = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  base = 0;
  dropPck = false;
  calen = sizeof(ca);

  getGet();

  return true;
}

bool getGet(){
	unsigned char packet[PAKSIZE + 1];
	rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
	return (rlen > 0) ? true : false;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == 0) return false; //doesn't matter, only for the old version (netwark)
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        //seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p (false, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

void loadWindow(){
	for(int i = base; i < base + WIN_SIZE; i++) {
		window[i-base] = createPacket(i);
		if(strlen(window[i-base].getDataBuffer()) < BUFSIZE - 1 && window[i-base].getDataBuffer()[0] != 'G') {
			for(++i; i < base + WIN_SIZE; i++){
				window[i-base].loadDataBuffer("\0");
			}
			return;
		}
	}
}

bool sendFile() {
	/*Currently causes the program to only send the first 16 packets of file out
		requires additional code later to sendFile again with updated window*/
	base = 0;
	while(base * BUFSIZE < length) {
		loadWindow();

		cout << "packet " << base << ": " << window[0].str() << endl;

		for(int x = 0; x < WIN_SIZE; x++) {
			p = window[x];
			if(!sendPacket()) continue;
		}
		if(p.str()[0] == '\0') break;
		for(int x = 0; x < WIN_SIZE; x++) {
			if(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
				cout << "=== ACK TIMEOUT" << endl;
				x--;
				continue;
			}

			if(isAck()) {
				handleAck();
			} else {
				handleAck();
				//handleNak(x);
			}

			memset(b, 0, BUFSIZE);
		}
	}

	if(sendto(s, "\0", BUFSIZE, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Final package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
	}
	return true;
}

Packet createPacket(int index){
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);

	if(mstr.length() < BUFSIZE) {
		cout << "Null terminated mstr." << endl;
		mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (index, mstr.c_str());
}

bool sendPacket(){
	cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	dropPck = pckStatus[0];
	delayPck = pckStatus[1];

	if (dropPck == true) return false;
	if (delayPck == true) p.setAckNack(1);

    if(sendto(s, p.str(), BUFSIZE + 8, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}
bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {
	int ack = boost::lexical_cast<int>(b);
	if(base < ack) base = ack;
	cout << "Window base: " << base << endl;
}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){

  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  packStatus[0] = false;
  packStatus[1] = false;

  if(r <= (lossProb)){
	packStatus[0] = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  packStatus[1] = true;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  //cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
// base_corpse.cc
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_base_corpse.h"
#include "obj_player_corpse.h"
#include "obj_base_corpse.h"
#include "obj_base_clothing.h"

TBaseCorpse::TBaseCorpse() :
  TBaseContainer(),
  corpse_flags(0),
  corpse_race(RACE_NORACE),
  corpse_level(0),
  corpse_vnum(-1),
  tDissections(NULL)
{
}

TBaseCorpse::TBaseCorpse(const TBaseCorpse &a) :
  TBaseContainer(a),
  corpse_flags(a.corpse_flags),
  corpse_race(a.corpse_race),
  corpse_level(a.corpse_level),
  corpse_vnum(a.corpse_vnum),
  tDissections(a.tDissections)
{
}

TBaseCorpse & TBaseCorpse::operator=(const TBaseCorpse &a)
{
  if (this == &a) return *this;
  TBaseContainer::operator=(a);
  corpse_flags = a.corpse_flags;
  corpse_race = a.corpse_race;
  corpse_level = a.corpse_level;
  corpse_vnum = a.corpse_vnum;
  tDissections = a.tDissections;
  return *this;
}

TBaseCorpse::~TBaseCorpse()
{
  for (; getStuff(); ) {
    // assumption that corpse is not in another container
    // assumption that corpse is also not stuck in someone, or equipped
    TThing * t = getStuff();
    --(*t);
    if (parent)
      *parent += *t;
    else if (riding)
      t->mount(riding);
    else if (roomp)
      *roomp += *t;
    else {
      // the corpse wasn't owned by anything
      // this can happen if an immortal holds a corpse and quits
      //    as in: "Here, let me help you get rid of this stuff"
      // seems best solution (given how this can happen), is to junk stuff
      delete t;
    }
  }

  if (tDissections) {
    dissectInfo *tNextDissect = tDissections;

    for (; tNextDissect; tNextDissect = tDissections) {
      tDissections = tNextDissect->tNext;
      delete tNextDissect;
      tNextDissect = NULL;
    }

    tDissections = NULL;
  }
}

void TBaseCorpse::assignFourValues(int x1, int x2, int x3, int x4)
{
  setCorpseFlags(x1);
  setCorpseRace((race_t) x2);
  setCorpseLevel(x3);
  setCorpseVnum(x4);
}

void TBaseCorpse::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = getCorpseFlags();
  *x2 = getCorpseRace();
  *x3 = getCorpseLevel();
  *x4 = getCorpseVnum();
}

void TBaseCorpse::setCorpseFlags(unsigned int f)
{
  corpse_flags = f;
}

unsigned int TBaseCorpse::getCorpseFlags() const
{
  return corpse_flags;
}

void TBaseCorpse::addCorpseFlag(unsigned int r)
{
  corpse_flags |= r;
}

void TBaseCorpse::remCorpseFlag(unsigned int r)
{
  corpse_flags &= ~r;
}

bool TBaseCorpse::isCorpseFlag(unsigned int r) const
{
  return ((corpse_flags & r) != 0);
}

void TBaseCorpse::setCorpseRace(race_t r)
{
  corpse_race = r;
}

race_t TBaseCorpse::getCorpseRace() const
{
  return corpse_race;
}

void TBaseCorpse::setCorpseLevel(unsigned int r)
{
  corpse_level = r;
}

unsigned int TBaseCorpse::getCorpseLevel() const
{
  return corpse_level;
}

void TBaseCorpse::setCorpseVnum(int r)
{
  corpse_vnum = r;
}

int TBaseCorpse::getCorpseVnum() const
{
  return corpse_vnum;
}

void TBaseCorpse::peeOnMe(const TBeing *ch)
{
  act("With a scream of victory, $n pisses on $p.",
             TRUE, ch, this, NULL, TO_ROOM);
  act("You scream victoriously as you piss on $p.",
             TRUE, ch, this, NULL, TO_CHAR);
}

int TBaseCorpse::dissectMe(TBeing *caster)
{
  if (gamePort != PROD_GAMEPORT) {
    int          tValue,
                 tWhich = 0;
    TObj        *tObj;
    dissectInfo *tDissect;

    if (isCorpseFlag(CORPSE_NO_REGEN)) {
      act("$p: I am afraid that cannot be dissected.",
          FALSE, caster, this, 0, TO_CHAR);
      return FALSE;
    }

    if (!tDissections) {
      act("That has nothing of value anymore.",
          FALSE, caster, this, 0, TO_CHAR);
      return FALSE;
    }

    for (tDissect = tDissections; tDissect; tDissect = tDissect->tNext)
      tWhich++;

    vlogf(LOG_LAPSOS, "dissectMe: tWhich(%d)", tWhich);

    tWhich = ::number(0, tWhich);

    for (tDissect = tDissections; (tDissect && tWhich--); tDissect = tDissect->tNext);

    if (!tDissect && !(tDissect = tDissections)) {
      vlogf(LOG_LAPSOS, "dissectMe Error.  tDissect ended up NULL.");
      return FALSE;
    }

    if (!(tValue = real_object(tDissect->loadItem))) {
      act("That has nothing of value anymore.",
          FALSE, caster, this, 0, TO_CHAR);
      return FALSE;
    }

    act("You dissect $p.", FALSE, caster, this, 0, TO_CHAR);
    act("$n dissects $p.", FALSE, caster, this, 0, TO_ROOM);

    if (obj_index[tValue].number >= obj_index[tValue].max_exist) {
      // item at max
      act("You find nothing useful in $p.",
            FALSE, caster, this, 0, TO_CHAR);
      return TRUE;
    }

    if (!(tObj = read_object(tValue, REAL))) {
      caster->sendTo("Serious problem in dissect.\n\r");
      vlogf(LOG_OBJ, "Bad call to read_object in dissect, num %d", tValue);
      return FALSE;
    }

    int bKnown = caster->getSkillValue(SKILL_DISSECT);

    if (!bSuccess(caster, bKnown, SKILL_DISSECT) &&
        !caster->hasQuestBit(TOG_STARTED_MONK_BLUE)) {
      // dissection failed
      act("You find nothing useful in $p.",
            FALSE, caster, this, 0, TO_CHAR);
      delete tObj;
      tObj = NULL;
      return TRUE;
    } else {
      if (::number(0,99) >= (signed) tDissect->amount) {
        // failed to pass amount
        CF(SKILL_DISSECT);
        act("You find nothing useful in $p.",
              FALSE, caster, this, 0, TO_CHAR);
        delete tObj;
        tObj = NULL;
        return TRUE;
      }

      if (caster->hasQuestBit(TOG_STARTED_MONK_BLUE))
        caster->setQuestBit(TOG_MONK_KILLED_SHARK);

      *caster += *tObj;
      act(tDissect->message_to_self.c_str(),
          FALSE, caster, tObj, this, TO_CHAR);
      act(tDissect->message_to_others.c_str(),
          FALSE, caster, tObj, this, TO_ROOM);

      if (--tDissect->count <= 0) {
        if (tDissections == tDissect)
          tDissections = tDissect->tNext;
        else {
          dissectInfo *tDissectNext;

          for (tDissectNext = tDissections; tDissectNext->tNext != tDissect;
               tDissectNext = tDissectNext->tNext);

          tDissectNext->tNext = tDissect->tNext;
        }

        delete tDissect;
        tDissect = NULL;
      }

      return TRUE;
    }
  } else {
    int num = -1, rnum;
    int amount = 100;
    TObj *obj;
    char msg[256], gl_msg[256];

    if (isCorpseFlag(CORPSE_NO_REGEN)) {
      // a body part or something
      act("$p: You aren't able to dissect that.",
            FALSE, caster, this, 0, TO_CHAR);
      return FALSE;
    }
    if (isCorpseFlag(CORPSE_NO_DISSECT)) {
      // dissection already occurred
      act("Nothing more of any use can be taken from $p.",
            FALSE, caster, this, 0, TO_CHAR);
      return FALSE;
    }
    num = determineDissectionItem(this, &amount, msg, gl_msg, caster);
    if (num == -1 || !(rnum = real_object(num))) {
      // no item
      act("You aren't aware of any useful dissections that come from $p.",
              FALSE, caster, this, 0, TO_CHAR);
      return TRUE;
    }

    act("You dissect $p.", FALSE, caster, this, 0, TO_CHAR);
    act("$n dissects $p.", FALSE, caster, this, 0, TO_ROOM);
    addCorpseFlag(CORPSE_NO_DISSECT);

    if (obj_index[rnum].number >= obj_index[rnum].max_exist) {
      // item at max
      act("You find nothing useful in $p.",
            FALSE, caster, this, 0, TO_CHAR);
      return TRUE;
    }
    if (!(obj = read_object(num, VIRTUAL))) {
      caster->sendTo("Serious problem in dissect.\n\r");
      vlogf(LOG_OBJ, "Bad call to read_object in dissect, num %d", num);
      return FALSE;
    }
    int bKnown = caster->getSkillValue(SKILL_DISSECT);

    if (!bSuccess(caster, bKnown, SKILL_DISSECT) &&
        !caster->hasQuestBit(TOG_STARTED_MONK_BLUE)) {
      // dissection failed
      act("You find nothing useful in $p.",
            FALSE, caster, this, 0, TO_CHAR);
      delete obj;
      obj = NULL;
      return TRUE;
    } else {
      if (::number(0,99) >= amount) {
        // failed to pass amount
        CF(SKILL_DISSECT);
        act("You find nothing useful in $p.",
              FALSE, caster, this, 0, TO_CHAR);
        delete obj;
        obj = NULL;
        return TRUE;
      }

      if(caster->hasQuestBit(TOG_STARTED_MONK_BLUE)){
        caster->setQuestBit(TOG_MONK_KILLED_SHARK);
      }

      *caster += *obj;
      act(   msg, FALSE, caster, obj, this, TO_CHAR);
      act(gl_msg, FALSE, caster, obj, this, TO_ROOM);
      return TRUE;
    }
  }

  return TRUE;
}

void TBaseCorpse::update(int use)
{
  if (getStuff())
    getStuff()->update(use);

  if (nextThing) {
    if (nextThing != this)
      nextThing->update(use);
  }
}

void TBaseCorpse::lookObj(TBeing *ch, int) const
{
  act("$p contains:",TRUE, ch, this, 0, TO_CHAR);
  list_in_heap(getStuff(), ch, 0, 100);
  return;
}

int TBaseCorpse::putSomethingInto(TBeing *ch, TThing *)
{
  // technically, would be OK since is a container, but prevent them anyhow
  act("Unfortunately, you can't put things into $p.",
             FALSE, ch, this, 0, TO_CHAR);
  return 2;
}

int TBaseCorpse::scavengeMe(TBeing *ch, TObj **)
{
  TThing *t;
  TObj *obj;
  wearSlotT sl;
  char buf[256], buf2[256], buf3[256];
  int rc;

  if (!::number(0, 5) && getStuff()) {
    for (t = getStuff(); t; t = t->nextThing) {
      if (!t->getStuff() && (obj = dynamic_cast<TObj *>(t))) {
        sl = slot_from_bit(obj->obj_flags.wear_flags);
        if (dynamic_cast<TBaseClothing *>(obj)) {
          TObj *tobj = dynamic_cast<TObj *>(ch->equipment[sl]);
          if (obj->itemAC() < (tobj ?  tobj->itemAC() : 0)) {
            strcpy(buf2, obj->name);
            strcpy(buf3, name);
            add_bars(buf2);
            add_bars(buf3);
            sprintf(buf, "%s from %s", buf2, buf3);
            rc = ch->doGet(buf);
            if (IS_SET_DELETE(rc, DELETE_THIS))
              return DELETE_VICT;
            return TRUE;
          }
        }
      }
    }
  }
  return FALSE;
}

void TBaseCorpse::decayMe()
{
  if(obj_flags.decay_time>0){
    // corpses decay regardless of where they are
    obj_flags.decay_time--;
    canBeSeen++;
  }
}

int TBaseCorpse::objectDecay()
{
  if (parent)
    act("$p disintegrates in your hands.", FALSE, parent, this, 0, TO_CHAR);
  else if (roomp && roomp->getStuff()) {
    if (getMaterial() == MAT_POWDER) {
      sendrpf(COLOR_OBJECTS, roomp, "A gust of wind scatters %s.\n\r",
getName());
//      act("A gust of wind scatters $n.", TRUE, this, 0, 0, TO_ROOM);
    } else {
      sendrpf(COLOR_OBJECTS, roomp, "Flesh-eaters dissolve %s.\n\r", getName());
//      act("Flesh-eaters dissolve $n.", TRUE, this, 0, 0, TO_ROOM);
    }
  }
  ObjFromCorpse(this);
  return DELETE_THIS;
}

int TBaseCorpse::chiMe(TBeing *tLunatic)
{
  int     tMana  = ::number(10, 30),
          bKnown = tLunatic->getSkillLevel(SKILL_CHI);
  TThing *tThing;

  if (tLunatic->getMana() < tMana) {
    tLunatic->sendTo("You lack the chi to do this.\n\r");
    return RET_STOP_PARSING;
  } else
    tLunatic->reconcileMana(TYPE_UNDEFINED, 0, tMana);

  if (dynamic_cast<TPCorpse *>(this) ||
      !bSuccess(tLunatic, bKnown, SKILL_CHI) ||
      getCorpseLevel() > tLunatic->GetMaxLevel()) {
    act("You attempt to nuke $p, but it resists you.",
        FALSE, tLunatic, this, NULL, TO_CHAR);
    return true;
  }

  act("You focus your chi and set $p ablaze!",
      FALSE, tLunatic, this, NULL, TO_CHAR);
  act("$n stares at $p which suddenly bursts into flames!",
      TRUE, tLunatic, this, NULL, TO_ROOM);

  while ((tThing = getStuff())) {
    --(*tThing);

    if (roomp)
      *roomp += *tThing;
    else if (parent)
      *parent += *tThing;
    else {
      vlogf(LOG_BUG, "Neither roomp nor parent in chiMe corpse.  Destorying %s",
            tThing->getName());
      delete tThing;
      tThing = NULL;
    }
  }

  return DELETE_VICT;
}
<commit_msg>removed lapsos's buggy test code for dissect which he enabled for everyone because he's a goddamn bastard<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
// base_corpse.cc
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_base_corpse.h"
#include "obj_player_corpse.h"
#include "obj_base_corpse.h"
#include "obj_base_clothing.h"

TBaseCorpse::TBaseCorpse() :
  TBaseContainer(),
  corpse_flags(0),
  corpse_race(RACE_NORACE),
  corpse_level(0),
  corpse_vnum(-1),
  tDissections(NULL)
{
}

TBaseCorpse::TBaseCorpse(const TBaseCorpse &a) :
  TBaseContainer(a),
  corpse_flags(a.corpse_flags),
  corpse_race(a.corpse_race),
  corpse_level(a.corpse_level),
  corpse_vnum(a.corpse_vnum),
  tDissections(a.tDissections)
{
}

TBaseCorpse & TBaseCorpse::operator=(const TBaseCorpse &a)
{
  if (this == &a) return *this;
  TBaseContainer::operator=(a);
  corpse_flags = a.corpse_flags;
  corpse_race = a.corpse_race;
  corpse_level = a.corpse_level;
  corpse_vnum = a.corpse_vnum;
  tDissections = a.tDissections;
  return *this;
}

TBaseCorpse::~TBaseCorpse()
{
  for (; getStuff(); ) {
    // assumption that corpse is not in another container
    // assumption that corpse is also not stuck in someone, or equipped
    TThing * t = getStuff();
    --(*t);
    if (parent)
      *parent += *t;
    else if (riding)
      t->mount(riding);
    else if (roomp)
      *roomp += *t;
    else {
      // the corpse wasn't owned by anything
      // this can happen if an immortal holds a corpse and quits
      //    as in: "Here, let me help you get rid of this stuff"
      // seems best solution (given how this can happen), is to junk stuff
      delete t;
    }
  }

  if (tDissections) {
    dissectInfo *tNextDissect = tDissections;

    for (; tNextDissect; tNextDissect = tDissections) {
      tDissections = tNextDissect->tNext;
      delete tNextDissect;
      tNextDissect = NULL;
    }

    tDissections = NULL;
  }
}

void TBaseCorpse::assignFourValues(int x1, int x2, int x3, int x4)
{
  setCorpseFlags(x1);
  setCorpseRace((race_t) x2);
  setCorpseLevel(x3);
  setCorpseVnum(x4);
}

void TBaseCorpse::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = getCorpseFlags();
  *x2 = getCorpseRace();
  *x3 = getCorpseLevel();
  *x4 = getCorpseVnum();
}

void TBaseCorpse::setCorpseFlags(unsigned int f)
{
  corpse_flags = f;
}

unsigned int TBaseCorpse::getCorpseFlags() const
{
  return corpse_flags;
}

void TBaseCorpse::addCorpseFlag(unsigned int r)
{
  corpse_flags |= r;
}

void TBaseCorpse::remCorpseFlag(unsigned int r)
{
  corpse_flags &= ~r;
}

bool TBaseCorpse::isCorpseFlag(unsigned int r) const
{
  return ((corpse_flags & r) != 0);
}

void TBaseCorpse::setCorpseRace(race_t r)
{
  corpse_race = r;
}

race_t TBaseCorpse::getCorpseRace() const
{
  return corpse_race;
}

void TBaseCorpse::setCorpseLevel(unsigned int r)
{
  corpse_level = r;
}

unsigned int TBaseCorpse::getCorpseLevel() const
{
  return corpse_level;
}

void TBaseCorpse::setCorpseVnum(int r)
{
  corpse_vnum = r;
}

int TBaseCorpse::getCorpseVnum() const
{
  return corpse_vnum;
}

void TBaseCorpse::peeOnMe(const TBeing *ch)
{
  act("With a scream of victory, $n pisses on $p.",
             TRUE, ch, this, NULL, TO_ROOM);
  act("You scream victoriously as you piss on $p.",
             TRUE, ch, this, NULL, TO_CHAR);
}

int TBaseCorpse::dissectMe(TBeing *caster)
{
  int num = -1, rnum;
  int amount = 100;
  TObj *obj;
  char msg[256], gl_msg[256];

  if (isCorpseFlag(CORPSE_NO_REGEN)) {
    // a body part or something
    act("$p: You aren't able to dissect that.",
	FALSE, caster, this, 0, TO_CHAR);
    return FALSE;
  }
  if (isCorpseFlag(CORPSE_NO_DISSECT)) {
    // dissection already occurred
    act("Nothing more of any use can be taken from $p.",
	FALSE, caster, this, 0, TO_CHAR);
    return FALSE;
  }
  num = determineDissectionItem(this, &amount, msg, gl_msg, caster);
  if (num == -1 || !(rnum = real_object(num))) {
    // no item
    act("You aren't aware of any useful dissections that come from $p.",
	FALSE, caster, this, 0, TO_CHAR);
    return TRUE;
  }

  act("You dissect $p.", FALSE, caster, this, 0, TO_CHAR);
  act("$n dissects $p.", FALSE, caster, this, 0, TO_ROOM);
  addCorpseFlag(CORPSE_NO_DISSECT);

  if (obj_index[rnum].number >= obj_index[rnum].max_exist) {
    // item at max
    act("You find nothing useful in $p.",
	FALSE, caster, this, 0, TO_CHAR);
    return TRUE;
  }
  if (!(obj = read_object(num, VIRTUAL))) {
    caster->sendTo("Serious problem in dissect.\n\r");
    vlogf(LOG_OBJ, "Bad call to read_object in dissect, num %d", num);
    return FALSE;
  }
  int bKnown = caster->getSkillValue(SKILL_DISSECT);

  if (!bSuccess(caster, bKnown, SKILL_DISSECT) &&
      !caster->hasQuestBit(TOG_STARTED_MONK_BLUE)) {
    // dissection failed
    act("You find nothing useful in $p.",
	FALSE, caster, this, 0, TO_CHAR);
    delete obj;
    obj = NULL;
    return TRUE;
  } else {
    if (::number(0,99) >= amount) {
      // failed to pass amount
      CF(SKILL_DISSECT);
      act("You find nothing useful in $p.",
	  FALSE, caster, this, 0, TO_CHAR);
      delete obj;
      obj = NULL;
      return TRUE;
    }

    if(caster->hasQuestBit(TOG_STARTED_MONK_BLUE)){
      caster->setQuestBit(TOG_MONK_KILLED_SHARK);
    }

    *caster += *obj;
    act(   msg, FALSE, caster, obj, this, TO_CHAR);
    act(gl_msg, FALSE, caster, obj, this, TO_ROOM);
    return TRUE;
  }

  return TRUE;
}

void TBaseCorpse::update(int use)
{
  if (getStuff())
    getStuff()->update(use);

  if (nextThing) {
    if (nextThing != this)
      nextThing->update(use);
  }
}

void TBaseCorpse::lookObj(TBeing *ch, int) const
{
  act("$p contains:",TRUE, ch, this, 0, TO_CHAR);
  list_in_heap(getStuff(), ch, 0, 100);
  return;
}

int TBaseCorpse::putSomethingInto(TBeing *ch, TThing *)
{
  // technically, would be OK since is a container, but prevent them anyhow
  act("Unfortunately, you can't put things into $p.",
             FALSE, ch, this, 0, TO_CHAR);
  return 2;
}

int TBaseCorpse::scavengeMe(TBeing *ch, TObj **)
{
  TThing *t;
  TObj *obj;
  wearSlotT sl;
  char buf[256], buf2[256], buf3[256];
  int rc;

  if (!::number(0, 5) && getStuff()) {
    for (t = getStuff(); t; t = t->nextThing) {
      if (!t->getStuff() && (obj = dynamic_cast<TObj *>(t))) {
        sl = slot_from_bit(obj->obj_flags.wear_flags);
        if (dynamic_cast<TBaseClothing *>(obj)) {
          TObj *tobj = dynamic_cast<TObj *>(ch->equipment[sl]);
          if (obj->itemAC() < (tobj ?  tobj->itemAC() : 0)) {
            strcpy(buf2, obj->name);
            strcpy(buf3, name);
            add_bars(buf2);
            add_bars(buf3);
            sprintf(buf, "%s from %s", buf2, buf3);
            rc = ch->doGet(buf);
            if (IS_SET_DELETE(rc, DELETE_THIS))
              return DELETE_VICT;
            return TRUE;
          }
        }
      }
    }
  }
  return FALSE;
}

void TBaseCorpse::decayMe()
{
  if(obj_flags.decay_time>0){
    // corpses decay regardless of where they are
    obj_flags.decay_time--;
    canBeSeen++;
  }
}

int TBaseCorpse::objectDecay()
{
  if (parent)
    act("$p disintegrates in your hands.", FALSE, parent, this, 0, TO_CHAR);
  else if (roomp && roomp->getStuff()) {
    if (getMaterial() == MAT_POWDER) {
      sendrpf(COLOR_OBJECTS, roomp, "A gust of wind scatters %s.\n\r",
getName());
//      act("A gust of wind scatters $n.", TRUE, this, 0, 0, TO_ROOM);
    } else {
      sendrpf(COLOR_OBJECTS, roomp, "Flesh-eaters dissolve %s.\n\r", getName());
//      act("Flesh-eaters dissolve $n.", TRUE, this, 0, 0, TO_ROOM);
    }
  }
  ObjFromCorpse(this);
  return DELETE_THIS;
}

int TBaseCorpse::chiMe(TBeing *tLunatic)
{
  int     tMana  = ::number(10, 30),
          bKnown = tLunatic->getSkillLevel(SKILL_CHI);
  TThing *tThing;

  if (tLunatic->getMana() < tMana) {
    tLunatic->sendTo("You lack the chi to do this.\n\r");
    return RET_STOP_PARSING;
  } else
    tLunatic->reconcileMana(TYPE_UNDEFINED, 0, tMana);

  if (dynamic_cast<TPCorpse *>(this) ||
      !bSuccess(tLunatic, bKnown, SKILL_CHI) ||
      getCorpseLevel() > tLunatic->GetMaxLevel()) {
    act("You attempt to nuke $p, but it resists you.",
        FALSE, tLunatic, this, NULL, TO_CHAR);
    return true;
  }

  act("You focus your chi and set $p ablaze!",
      FALSE, tLunatic, this, NULL, TO_CHAR);
  act("$n stares at $p which suddenly bursts into flames!",
      TRUE, tLunatic, this, NULL, TO_ROOM);

  while ((tThing = getStuff())) {
    --(*tThing);

    if (roomp)
      *roomp += *tThing;
    else if (parent)
      *parent += *tThing;
    else {
      vlogf(LOG_BUG, "Neither roomp nor parent in chiMe corpse.  Destorying %s",
            tThing->getName());
      delete tThing;
      tThing = NULL;
    }
  }

  return DELETE_VICT;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2017-2018 Hans-Kristian Arntzen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include "cookie.hpp"
#include "hashmap.hpp"
#include "image.hpp"
#include "intrusive.hpp"
#include "limits.hpp"
#include "object_pool.hpp"
#include "temporary_hashmap.hpp"
#include "vulkan.hpp"

namespace Vulkan
{
enum RenderPassOp
{
	RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT = 1 << 0,
	RENDER_PASS_OP_LOAD_DEPTH_STENCIL_BIT = 1 << 1,

	RENDER_PASS_OP_STORE_DEPTH_STENCIL_BIT = 1 << 2,

	RENDER_PASS_OP_COLOR_OPTIMAL_BIT = 1 << 3,
	RENDER_PASS_OP_DEPTH_STENCIL_OPTIMAL_BIT = 1 << 4,
	RENDER_PASS_OP_DEPTH_STENCIL_READ_ONLY_BIT = 1 << 5
};
using RenderPassOpFlags = uint32_t;

class ImageView;
struct RenderPassInfo
{
	ImageView *color_attachments[VULKAN_NUM_ATTACHMENTS];
	ImageView *depth_stencil = nullptr;
	unsigned num_color_attachments = 0;
	RenderPassOpFlags op_flags = 0;
	uint32_t clear_attachments = 0;
	uint32_t load_attachments = 0;
	uint32_t store_attachments = 0;

	// Render area will be clipped to the actual framebuffer.
	VkRect2D render_area = { { 0, 0 }, { UINT32_MAX, UINT32_MAX } };

	VkClearColorValue clear_color[VULKAN_NUM_ATTACHMENTS] = {};
	VkClearDepthStencilValue clear_depth_stencil = { 1.0f, 0 };

	enum class DepthStencil
	{
		None,
		ReadOnly,
		ReadWrite
	};

	struct Subpass
	{
		uint32_t color_attachments[VULKAN_NUM_ATTACHMENTS];
		uint32_t input_attachments[VULKAN_NUM_ATTACHMENTS];
		uint32_t resolve_attachments[VULKAN_NUM_ATTACHMENTS];
		unsigned num_color_attachments = 0;
		unsigned num_input_attachments = 0;
		unsigned num_resolve_attachments = 0;
		DepthStencil depth_stencil_mode = DepthStencil::ReadWrite;
	};
	// If 0/nullptr, assume a default subpass.
	const Subpass *subpasses = nullptr;
	unsigned num_subpasses = 0;
};

class RenderPass : public HashedObject, public NoCopyNoMove
{
public:
	struct SubpassInfo
	{
		VkAttachmentReference color_attachments[VULKAN_NUM_ATTACHMENTS];
		unsigned num_color_attachments;
		VkAttachmentReference input_attachments[VULKAN_NUM_ATTACHMENTS];
		unsigned num_input_attachments;
		VkAttachmentReference depth_stencil_attachment;

		unsigned samples;
	};

	RenderPass(Util::Hash hash, Device *device, const RenderPassInfo &info);
	RenderPass(Util::Hash hash, Device *device, const VkRenderPassCreateInfo &create_info);
	~RenderPass();

	unsigned get_num_subpasses() const
	{
		return subpasses.size();
	}

	VkRenderPass get_render_pass() const
	{
		return render_pass;
	}

	uint32_t get_sample_count(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].samples;
	}

	unsigned get_num_color_attachments(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].num_color_attachments;
	}

	unsigned get_num_input_attachments(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].num_input_attachments;
	}

	const VkAttachmentReference &get_color_attachment(unsigned subpass, unsigned index) const
	{
		VK_ASSERT(subpass < subpasses.size());
		VK_ASSERT(index < subpasses[subpass].num_color_attachments);
		return subpasses[subpass].color_attachments[index];
	}

	const VkAttachmentReference &get_input_attachment(unsigned subpass, unsigned index) const
	{
		VK_ASSERT(subpass < subpasses.size());
		VK_ASSERT(index < subpasses[subpass].num_input_attachments);
		return subpasses[subpass].input_attachments[index];
	}

	bool has_depth(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED &&
		       format_is_depth(depth_stencil);
	}

	bool has_stencil(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED &&
		       (format_is_depth_stencil(depth_stencil) || format_is_stencil(depth_stencil));
	}

private:
	Device *device;
	VkRenderPass render_pass = VK_NULL_HANDLE;

	VkFormat color_attachments[VULKAN_NUM_ATTACHMENTS] = {};
	VkFormat depth_stencil = VK_FORMAT_UNDEFINED;
	std::vector<SubpassInfo> subpasses;

	void setup_subpasses(const VkRenderPassCreateInfo &create_info);
};

class Framebuffer : public Cookie, public NoCopyNoMove, public InternalSyncEnabled
{
public:
	Framebuffer(Device *device, const RenderPass &rp, const RenderPassInfo &info);
	~Framebuffer();

	VkFramebuffer get_framebuffer() const
	{
		return framebuffer;
	}

	ImageView *get_attachment(unsigned index) const
	{
		assert(index < attachments.size());
		return attachments[index];
	}

	uint32_t get_width() const
	{
		return width;
	}

	uint32_t get_height() const
	{
		return height;
	}

	const RenderPass &get_render_pass() const
	{
		return render_pass;
	}

private:
	Device *device;
	VkFramebuffer framebuffer = VK_NULL_HANDLE;
	const RenderPass &render_pass;
	RenderPassInfo info;
	uint32_t width = 0;
	uint32_t height = 0;

	std::vector<ImageView *> attachments;
};

static const unsigned VULKAN_FRAMEBUFFER_RING_SIZE = 4;
class FramebufferAllocator
{
public:
	FramebufferAllocator(Device *device);
	Framebuffer &request_framebuffer(const RenderPassInfo &info);

	void begin_frame();
	void clear();

private:
	struct FramebufferNode : Util::TemporaryHashmapEnabled<FramebufferNode>,
	                         Util::IntrusiveListEnabled<FramebufferNode>,
	                         Framebuffer
	{
		FramebufferNode(Device *device, const RenderPass &rp, const RenderPassInfo &info)
		    : Framebuffer(device, rp, info)
		{
			set_internal_sync_object();
		}
	};

	Device *device;
	Util::TemporaryHashmap<FramebufferNode, VULKAN_FRAMEBUFFER_RING_SIZE, false> framebuffers;
	std::mutex lock;
};

class AttachmentAllocator
{
public:
	AttachmentAllocator(Device *device, bool transient)
		: device(device), transient(transient)
	{
	}

	ImageView &request_attachment(unsigned width, unsigned height, VkFormat format,
	                              unsigned index = 0, unsigned samples = 1);

	void begin_frame();
	void clear();

private:
	struct TransientNode : Util::TemporaryHashmapEnabled<TransientNode>, Util::IntrusiveListEnabled<TransientNode>
	{
		TransientNode(ImageHandle handle)
		    : handle(handle)
		{
		}

		ImageHandle handle;
	};

	Device *device;
	Util::TemporaryHashmap<TransientNode, VULKAN_FRAMEBUFFER_RING_SIZE, false> attachments;
	std::mutex lock;
	bool transient;
};

class TransientAttachmentAllocator : public AttachmentAllocator
{
public:
	TransientAttachmentAllocator(Device *device)
		: AttachmentAllocator(device, true)
	{
	}
};

class PhysicalAttachmentAllocator : public AttachmentAllocator
{
public:
	PhysicalAttachmentAllocator(Device *device)
		: AttachmentAllocator(device, false)
	{
	}
};

}

<commit_msg>Bump the framebuffer allocator ring buffer to 8 frames.<commit_after>/* Copyright (c) 2017-2018 Hans-Kristian Arntzen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include "cookie.hpp"
#include "hashmap.hpp"
#include "image.hpp"
#include "intrusive.hpp"
#include "limits.hpp"
#include "object_pool.hpp"
#include "temporary_hashmap.hpp"
#include "vulkan.hpp"

namespace Vulkan
{
enum RenderPassOp
{
	RENDER_PASS_OP_CLEAR_DEPTH_STENCIL_BIT = 1 << 0,
	RENDER_PASS_OP_LOAD_DEPTH_STENCIL_BIT = 1 << 1,

	RENDER_PASS_OP_STORE_DEPTH_STENCIL_BIT = 1 << 2,

	RENDER_PASS_OP_COLOR_OPTIMAL_BIT = 1 << 3,
	RENDER_PASS_OP_DEPTH_STENCIL_OPTIMAL_BIT = 1 << 4,
	RENDER_PASS_OP_DEPTH_STENCIL_READ_ONLY_BIT = 1 << 5
};
using RenderPassOpFlags = uint32_t;

class ImageView;
struct RenderPassInfo
{
	ImageView *color_attachments[VULKAN_NUM_ATTACHMENTS];
	ImageView *depth_stencil = nullptr;
	unsigned num_color_attachments = 0;
	RenderPassOpFlags op_flags = 0;
	uint32_t clear_attachments = 0;
	uint32_t load_attachments = 0;
	uint32_t store_attachments = 0;

	// Render area will be clipped to the actual framebuffer.
	VkRect2D render_area = { { 0, 0 }, { UINT32_MAX, UINT32_MAX } };

	VkClearColorValue clear_color[VULKAN_NUM_ATTACHMENTS] = {};
	VkClearDepthStencilValue clear_depth_stencil = { 1.0f, 0 };

	enum class DepthStencil
	{
		None,
		ReadOnly,
		ReadWrite
	};

	struct Subpass
	{
		uint32_t color_attachments[VULKAN_NUM_ATTACHMENTS];
		uint32_t input_attachments[VULKAN_NUM_ATTACHMENTS];
		uint32_t resolve_attachments[VULKAN_NUM_ATTACHMENTS];
		unsigned num_color_attachments = 0;
		unsigned num_input_attachments = 0;
		unsigned num_resolve_attachments = 0;
		DepthStencil depth_stencil_mode = DepthStencil::ReadWrite;
	};
	// If 0/nullptr, assume a default subpass.
	const Subpass *subpasses = nullptr;
	unsigned num_subpasses = 0;
};

class RenderPass : public HashedObject, public NoCopyNoMove
{
public:
	struct SubpassInfo
	{
		VkAttachmentReference color_attachments[VULKAN_NUM_ATTACHMENTS];
		unsigned num_color_attachments;
		VkAttachmentReference input_attachments[VULKAN_NUM_ATTACHMENTS];
		unsigned num_input_attachments;
		VkAttachmentReference depth_stencil_attachment;

		unsigned samples;
	};

	RenderPass(Util::Hash hash, Device *device, const RenderPassInfo &info);
	RenderPass(Util::Hash hash, Device *device, const VkRenderPassCreateInfo &create_info);
	~RenderPass();

	unsigned get_num_subpasses() const
	{
		return subpasses.size();
	}

	VkRenderPass get_render_pass() const
	{
		return render_pass;
	}

	uint32_t get_sample_count(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].samples;
	}

	unsigned get_num_color_attachments(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].num_color_attachments;
	}

	unsigned get_num_input_attachments(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].num_input_attachments;
	}

	const VkAttachmentReference &get_color_attachment(unsigned subpass, unsigned index) const
	{
		VK_ASSERT(subpass < subpasses.size());
		VK_ASSERT(index < subpasses[subpass].num_color_attachments);
		return subpasses[subpass].color_attachments[index];
	}

	const VkAttachmentReference &get_input_attachment(unsigned subpass, unsigned index) const
	{
		VK_ASSERT(subpass < subpasses.size());
		VK_ASSERT(index < subpasses[subpass].num_input_attachments);
		return subpasses[subpass].input_attachments[index];
	}

	bool has_depth(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED &&
		       format_is_depth(depth_stencil);
	}

	bool has_stencil(unsigned subpass) const
	{
		VK_ASSERT(subpass < subpasses.size());
		return subpasses[subpass].depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED &&
		       (format_is_depth_stencil(depth_stencil) || format_is_stencil(depth_stencil));
	}

private:
	Device *device;
	VkRenderPass render_pass = VK_NULL_HANDLE;

	VkFormat color_attachments[VULKAN_NUM_ATTACHMENTS] = {};
	VkFormat depth_stencil = VK_FORMAT_UNDEFINED;
	std::vector<SubpassInfo> subpasses;

	void setup_subpasses(const VkRenderPassCreateInfo &create_info);
};

class Framebuffer : public Cookie, public NoCopyNoMove, public InternalSyncEnabled
{
public:
	Framebuffer(Device *device, const RenderPass &rp, const RenderPassInfo &info);
	~Framebuffer();

	VkFramebuffer get_framebuffer() const
	{
		return framebuffer;
	}

	ImageView *get_attachment(unsigned index) const
	{
		assert(index < attachments.size());
		return attachments[index];
	}

	uint32_t get_width() const
	{
		return width;
	}

	uint32_t get_height() const
	{
		return height;
	}

	const RenderPass &get_render_pass() const
	{
		return render_pass;
	}

private:
	Device *device;
	VkFramebuffer framebuffer = VK_NULL_HANDLE;
	const RenderPass &render_pass;
	RenderPassInfo info;
	uint32_t width = 0;
	uint32_t height = 0;

	std::vector<ImageView *> attachments;
};

static const unsigned VULKAN_FRAMEBUFFER_RING_SIZE = 8;
class FramebufferAllocator
{
public:
	FramebufferAllocator(Device *device);
	Framebuffer &request_framebuffer(const RenderPassInfo &info);

	void begin_frame();
	void clear();

private:
	struct FramebufferNode : Util::TemporaryHashmapEnabled<FramebufferNode>,
	                         Util::IntrusiveListEnabled<FramebufferNode>,
	                         Framebuffer
	{
		FramebufferNode(Device *device, const RenderPass &rp, const RenderPassInfo &info)
		    : Framebuffer(device, rp, info)
		{
			set_internal_sync_object();
		}
	};

	Device *device;
	Util::TemporaryHashmap<FramebufferNode, VULKAN_FRAMEBUFFER_RING_SIZE, false> framebuffers;
	std::mutex lock;
};

class AttachmentAllocator
{
public:
	AttachmentAllocator(Device *device, bool transient)
		: device(device), transient(transient)
	{
	}

	ImageView &request_attachment(unsigned width, unsigned height, VkFormat format,
	                              unsigned index = 0, unsigned samples = 1);

	void begin_frame();
	void clear();

private:
	struct TransientNode : Util::TemporaryHashmapEnabled<TransientNode>, Util::IntrusiveListEnabled<TransientNode>
	{
		TransientNode(ImageHandle handle)
		    : handle(handle)
		{
		}

		ImageHandle handle;
	};

	Device *device;
	Util::TemporaryHashmap<TransientNode, VULKAN_FRAMEBUFFER_RING_SIZE, false> attachments;
	std::mutex lock;
	bool transient;
};

class TransientAttachmentAllocator : public AttachmentAllocator
{
public:
	TransientAttachmentAllocator(Device *device)
		: AttachmentAllocator(device, true)
	{
	}
};

class PhysicalAttachmentAllocator : public AttachmentAllocator
{
public:
	PhysicalAttachmentAllocator(Device *device)
		: AttachmentAllocator(device, false)
	{
	}
};

}

<|endoftext|>


<commit_before>#include <cassert>
#include <vSMC/rng/random.hpp>

int main ()
{
    int N = 100000;
    r123::Engine<V_SMC_CRNG_TYPE> eng(V_SMC_CRNG_SEED);

    vSMC::rng::bernoulli_distribution rbern(0.5);
    for (int i = 0; i != N; ++i){
        int b = rbern(eng);
        assert(b == 0 || b == 1);
    }

    vSMC::rng::binomial_distribution<> rbinom(20, 0.7);
    for (int i = 0; i != N; ++i) {
        int b = rbinom(eng);
        assert(b >= 0 && b <= 20);
    }

    vSMC::rng::gamma_distribution<> rgamma(1, 1);
    for (int i = 0; i != N; ++i) {
        double g = rgamma(eng);
        assert(g >= 0);
    }

    vSMC::rng::lognormal_distribution<> rlnom(1, 1);
    for (int i = 0; i != N; ++i) {
        double l = rlnom(eng);
        assert(l >= 0);
    }

    vSMC::rng::normal_distribution<> rnorm(0, 1);
    for (int i = 0; i != N; ++i) {
        double n = rnorm(eng);
    }

    vSMC::rng::uniform_real_distribution<> ruint(1, 100);
    for (int i = 0; i != N; ++i) {
        int u = ruint(eng);
        assert(u >= 1 && u <= 100);
    }

    vSMC::rng::uniform_real_distribution<> runif(0, 1);
    for (int i = 0; i != N; ++i) {
        double u = runif(eng);
        assert(u >= 0 && u <= 1);
    }

    return 0;
}
<commit_msg>fix and faster try_random<commit_after>#include <cassert>
#include <vSMC/rng/random.hpp>

int main ()
{
    int N = 10000;
    r123::Engine<V_SMC_CRNG_TYPE> eng(V_SMC_CRNG_SEED);

    vSMC::rng::uniform_real_distribution<> runif(0, 1);
    for (int i = 0; i != N; ++i) {
        int u = runif(eng);
        assert(u >= 0 && u <= 100);
    }

    vSMC::rng::uniform_int_distribution<> ruint(1, 100);
    for (int i = 0; i != N; ++i) {
        int u = ruint(eng);
        assert(u >= 1 && u <= 100);
    }

    vSMC::rng::bernoulli_distribution rbern(0.5);
    for (int i = 0; i != N; ++i){
        int b = rbern(eng);
        assert(b == 0 || b == 1);
    }

    vSMC::rng::binomial_distribution<> rbinom(20, 0.7);
    for (int i = 0; i != N; ++i) {
        int b = rbinom(eng);
        assert(b >= 0 && b <= 20);
    }

    vSMC::rng::gamma_distribution<> rgamma(1, 1);
    for (int i = 0; i != N; ++i) {
        double g = rgamma(eng);
        assert(g >= 0);
    }

    vSMC::rng::lognormal_distribution<> rlnom(1, 1);
    for (int i = 0; i != N; ++i) {
        double l = rlnom(eng);
        assert(l >= 0);
    }

    vSMC::rng::normal_distribution<> rnorm(0, 1);
    for (int i = 0; i != N; ++i) {
        double n = rnorm(eng);
    }

    return 0;
}
<|endoftext|>